多態描述的是使用基類的指針或引用操作多個類型的能力。
我們知道,子類的指針是可以隱式轉化為父類的,所以我們在進行程序設計的時候如果要對一個未知的類型進行處理,可以在方法聲明時把參數的類型聲明為父類的指針。
這要我們就是實現了根據傳入的類型執行不同的方法。這裡的關鍵是子類在重寫父類的虛方法時是在虛方法表的相應位置對父類虛方法實現覆蓋。
舉個例子:
頭文件classFile.h:
- #ifndef classFile_Header_File
- #define classFile_Header_File
- class father
- {
- public:
- virtual void show();
- };
- class son: public father
- {
- public:
- void show();
- void sayhi();
- };
- #endif
這裡我們在子類中對父類實現了overrideC++沒有提供override關鍵字,所以改寫父類的方法要格外小心)。
TestPoly.cpp代碼如下:
- #include<iostream>
- #include"classFile.h"
- using namespace std;
- void hello(father* fp)
- {
- fp->show();
- }
- int main()
- {
- father f;
- hello(&f);
- son s;
- hello(&f);
- }
- inline void father::show()
- {
- cout<<"I am father"<<endl;
- }
- inline void son::show()
- {
- cout<<"I am son"<<endl;
- }
- inline void son::sayhi()
- {
- cout<<"Hi, I am son"<<endl;
- }
這裡,傳入父類的指針將調用father::show(),傳入子類的指針時,雖然進行了隱式的類型轉化,但是由於子類在其繼承的虛方法表中相應的位置覆蓋了父類的show()方法,所用調用的實際上son::show()的內容。此時子類的方法表中不存在father::show()了,如果我們把virtual關鍵字去掉,那麼father::show()和son::show()將同時存在與子類的方法表中。
那麼如果子類做了父類沒用做的事情,我們應如何調用了?
比如這裡,我們的子類中實現了sayhi()方法,這是父類指針father*無法獲取到的地址實際是無法直接獲取到,通過手動的指針偏移還是可以的,不知道是C++的優點還是缺點),這個地方,如果我們能夠通過實際傳入的對象指針類型進行操作就OK了。還好C++為我們提過了這個功能,那就是引入關鍵字dynamic_cast。
我們把hello()函數改寫如下:
- void hello(father* fp)
- {
- son* ps=dynamic_cast<son*>(fp);//將fp 轉換為son*類型
- if(ps)//如果轉換失敗則返回0
- ps->sayhi();
- else
- fp->show();
- }
調用:
- int main()
- {
- father f;
- hello(&f);//轉換失敗,執行else
- son s;
- hello(&s); //輸出Hi,I am son
- }
以下這篇博文對虛函數表講解非常清楚:
http://blog.csdn.net/hairetz/archive/2009/04/29/4137000.aspx