1、多態的意義
如果有幾個上似而不完全相同的對象,有時人們要求在向它們發出同一個消息時, 它們的反應各不相同,分別執行不同的操作。這種情況就是多態現象。
C++中所謂的多態(polymorphism)是指,由繼承而產生的相關的不同的類,其對象對同一消息會作出不同的響應。
2、多態的三個必要條件
- 要有繼承
- 要有虛函數重寫
- 要有父類指針(父類引用)指向子類對象
#include <iostream> #include <string> using namespace std; class Yuebuqun { public: Yuebuqun(string kongfu) { this->kongfu = kongfu; } virtual void fight()//表示修飾一個成員方法是一個虛函數,必要條件2 { cout << "岳不群" << "使用了" << this->kongfu << endl; } string kongfu; }; //林平之繼承了岳不群 class Linpingzhi :public Yuebuqun { public: Linpingzhi(string kongfu) :Yuebuqun(kongfu) { } //如果說父類中有一個虛函數是fight(),子類如果去重寫這個虛函數, //那么如果傳遞進來的是子類,調用子類的fight,如果傳遞進來的是父類,調用父類的fight void fight()//必要條件2 { cout << "林平之" << "使用了" << kongfu << endl; } }; //令狐沖繼承了岳不群 class Linghuchong :public Yuebuqun { public: Linghuchong(string kongfu) :Yuebuqun(kongfu) { } void fight() { cout << "令狐沖" << "使用了" << kongfu << endl; } }; //在全局提供一個打斗的方法 void fightPeople(Yuebuqun *hero)//必要條件3,相當於Yuebuqun *hero = xiaopp;或Yuebuqun *hero = xiaoyy; //或Yuebuqun *hero = xiaoll; { hero->fight();//希望如果傳遞進來的是子類,調用子類的fight; //如果傳遞進來的是父類,調用父類的fight //這種行為就是多態行為 } //多態發生的三個必要條件: //1.要有繼承 //2.要有虛函數重寫 //3.父類指針或引用指向子類對象 int main(void) { Yuebuqun *xiaoyy = new Yuebuqun("葵花寶典"); xiaoyy->fight(); Linpingzhi *xiaopp = new Linpingzhi("辟邪劍譜"); xiaopp->fight(); Linghuchong *xiaoll = new Linghuchong("獨孤九劍"); xiaoll->fight(); //多態的實現 fightPeople(xiaoyy);//岳不群使用了葵花寶典 fightPeople(xiaopp);//林平之使用了辟邪劍譜 fightPeople(xiaoll);//令狐沖使用了獨孤九劍 //編譯器默認做了一個安全的處理,編譯認為不管傳遞時子類對象還是父類對象, //如果統一執行父類的方法,那么一定可以被成功執行。 delete xiaoyy; delete xiaopp; delete xiaoll; return 0; }
3、靜態聯編和動態聯編
(1)聯編是指一個程序模塊、代碼之間互相關聯的過程。
(2)靜態聯編,是程序的匹配、連接在編譯階段實現,也稱為早期匹配。重載函數使用靜態聯編。
(3)動態聯編是指程序聯編推遲到運行時進行,所以又稱為晚期聯編(遲邦定)。switch語句和if語句是動態聯編的例子。
1、C++與C相同,是靜態編譯型語言;
2、在編譯時,編譯器自動根據指針的類型判斷指向的是一個什么樣的對象;所以編譯器認為父類指針指向的是父類對象;
3、由於程序沒有運行,所以不可能知道父類指針指向的具體是父類對象還是子類對象,從程序安全的角度,編譯器假設父類指針只指向父類對象,因此編譯的結果為調用父類的成員函數。這種特性就是靜態聯編;
4、多態的發生是動態聯編,實在程序執行的時候判斷具體父類指針應該調用的方法。
4、虛析構函數
- 構造函數不能是虛函數。建立一個派生類對象時,必須從類層次的根開始,沿着繼承路徑逐個調用基類的構造函數。
- 析構函數可以是虛的。虛析構函數用於指引delete運算符正確析構動態對象。
5、重載重寫重定義
重載(添加)
a、相同的范圍(在同一個類中)
b、函數名字相同
c、參數不同
d、virtual可有可無
重寫(覆蓋) 是指派生類函數覆蓋基類函數,特征是:
a、不同的范圍,分別位於基類和派生類中
b、函數名字相同
c、參數相同
d、基類函數必須有virtual關鍵字
重定義(隱藏) 是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
a、如果派生類的函數和基類的函數同名,但是參數不同,此時,不管有無virtual,基類的函數被隱藏。
b、如果派生類的函數與基類的函數同名,但是參數也相同,但是基類函數沒有virtual關鍵字,此時,基類的函數被隱藏。
