父類子類指針函數調用注意事項
1,若是以一個基礎類指針指向一個衍生類對象(派生類對象),那麼經由該指針只能訪問基礎類定義的函數(靜態聯翩)
2,若是以一個衍生類指針指向一個基礎類對象,必須先作強制轉型動做(explicit cast),這種作法很危險,也不符合生活習慣,在程序設計上也會給程序員帶來困擾。(通常不會這麼去定義)
3,若是基礎類和衍生類定義了相同名稱的成員函數,那麼經過對象指針調用成員函數時,到底調用那個函數要根據指針的原型來肯定,而不是根據指針實際指向的對象類型肯定。ios
虛擬函數就是爲了對「若是你以一個基礎類指針指向一個衍生類對象,那麼經過該指針,你只能訪問基礎類定義的成員函數」這條規則反其道而行之的設計。
若是你預期衍生類由可能從新定義一個成員函數,那麼你就把它定義成虛擬函數( 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() 函數