父類子類指針函數調用注意事項
1,如果以一個基礎類指針指向一個衍生類對象(派生類對象),那么經由該指針只能訪問基礎類定義的函數(靜態聯翩)
2,如果以一個衍生類指針指向一個基礎類對象,必須先做強制轉型動作(explicit cast),這種做法很危險,也不符合生活習慣,在程序設計上也會給程序員帶來困擾。(一般不會這么去定義)
3,如果基礎類和衍生類定義了相同名稱的成員函數,那么通過對象指針調用成員函數時,到底調用那個函數要根據指針的原型來確定,而不是根據指針實際指向的對象類型確定。
虛擬函數就是為了對“如果你以一個基礎類指針指向一個衍生類對象,那么通過該指針,你只能訪問基礎類定義的成員函數”這條規則反其道而行之的設計。
如果你預期衍生類由可能重新定義一個成員函數,那么你就把它定義成虛擬函數( virtual )。
polymorphism就是讓處理基礎類別對象的程序代碼能夠通透的繼續適當地處理衍生類對象。
純虛擬函數:
virtual void myfunc ( ) =0;
純虛擬函數不許定義其具體動作,它的存在只是為了在衍生類鍾被重新定義。只要是擁有純虛擬函數的類,就是抽象類,它們是不能夠被實例化的(只能被繼承)。如果一個繼承類沒有改寫父類中的純虛函數,那么他也是抽象類,也不能被實例化。
抽象類不能被實例化,不過我們可以擁有指向抽象類的指針,以便於操縱各個衍生類。
虛擬函數衍生下去仍然是虛擬函數,而且還可以省略掉關鍵字“virtual”。
看個例子:
#include <iostream> using namespace std; class A { public: virtual void foo() { cout << "A's foo()" << endl; bar(); } virtual void bar() { cout << "A's bar()" << endl; } }; class B: public A { public: void foo() { cout << "B's foo()" << endl; A::foo(); } void bar() { cout << "B's bar()" << endl; } }; int main() { B bobj; A *aptr = &bobj; aptr->foo(); A aobj = *aptr; //轉化為A類對象 aobj.foo(); }
aptr->foo()輸出結果是:
B's foo()//這個明白,多態性
A's foo()//這個也明白,執行A::foo();
B's bar()//雖然調用的是這個函數:A::foo(); 但隱式傳入的還是bobj 的地址,所以再次調用bar();調用時還是會調用B的函數, 與虛函數指針有關
aobj.foo()輸出結果是:
A's foo() //這個不是指針,aobj完全是一個A的對象,與多態沒有關系
A's bar()