Preface
之前曾經介紹過函式與運算子的重載(Overload),重載可以使用一個函式名稱來執行不同的實作,這是一種「編譯時期」就需決定的方式,這是「早期繫 結」(Early binding)、「靜態繫結」(Static binding),因為在編譯時就可以決定函式的呼叫對象,它們的呼叫位址在編譯時就可以得知。
Virtual Function
「虛擬函式」(Virtual function)可以實現「執行時期」的多型支援,是一個「晚期繫結」(Late binding)、「動態繫結」(Dynamic binding),必須在執行時期才會得知所要調用的物件或其上的公開介面。一個基底類別的物件指標,可以用來指向其衍生類別物件而不會發生錯誤,例如若基底類別是 Foo1,而衍生類別是 Foo2,則 下面這個指定是可以接受的:
- Foo1 *fptr;
- Foo2 f2;
- fptr = &f2;
虛擬函式是一種成員函式,它在基底類別中使用關鍵字 "virtual" 宣告(定義),並在衍生類別中重新定義虛擬函式,這將成員函式的操作決議 (Resolution)推遲至執行時期再決定。
虛擬函式可以實現執行時期的「多型」,也就是「一個介面,多種函式」,一個含有虛擬函式的類別被稱為「多型的類別」(Polymorphic class),當一個基底類別型態的指標指向一個含有虛擬函式的衍生類別,您就可以使用這個指標來存取衍生類別中的虛擬函式,下面這個例子是個簡單的示 範:
- testVirtualFunc.cpp
- #include
- using namespace std;
- class Foo1 {
- public:
- virtual void show() { // 虛擬函式
- cout << "Foo1's show" << endl;
- }
- };
- class Foo2 : public Foo1 {
- public:
- virtual void show() { // 虛擬函式
- cout << "Foo2's show" << endl;
- }
- };
- void showFooByPtr(Foo1 *foo) {
- foo->show();
- }
- void showFooByRef(Foo1 &foo) {
- foo.show();
- }
- int main() {
- Foo1 f1;
- Foo2 f2;
- Foo1 *f1Ptr=&f2;
- // 動態繫結
- cout << "\t[Info] Show Foo By Ptr:" << endl;
- showFooByPtr(&f1);
- showFooByPtr(&f2);
- showFooByPtr(f1Ptr);
- cout << endl;
- // 動態繫結
- cout << "\t[Info] Show Foo By Ref:" << endl;
- showFooByRef(f1);
- showFooByRef(f2);
- cout << endl;
- // 靜態繫結
- cout << "\t[Info] Show Foo By Object:" << endl;
- f1.show();
- f2.show();
- cout << endl;
- return 0;
- }
如果把 Foo1 的 virtual 拿掉, 則執行結果為:
showFooByPtr() 與 showFooByRef() 函式並無法事先知道要操作的是哪一個物件的哪一個公開介面,最後的操作要在執行時期才能決 定。衍生類別中重新定義虛擬函式時,virtual 可以根據需求加上,如果再接下來的衍生類別仍想進行多型操作,則加上 virtual ,如果不打算進行多型操 作,則可以不加上。
沒有留言:
張貼留言