多態(tài)原理
當類存在虛函數(shù)時戈擒,編譯器會為該類維護一個表,這個表就是虛函數(shù)表(vtbl)习瑰,里面存放了該類虛函數(shù)的函數(shù)指針。在構造類的時候增加一個虛表指針(vptr)指向對應的虛函數(shù)表。在類執(zhí)行成員函數(shù)時候,先判斷該函數(shù)是否是虛函數(shù),如果不是虛函數(shù)則直接執(zhí)行對應的方法胁勺,如果是虛函數(shù)則從虛函數(shù)表中找到應該調用的函數(shù)涌穆。
- vptr的初始化是在類的構造時候完成怔昨。而在進行父類構造的時候,vptr指向的是父類vtbl宿稀。執(zhí)行完子類的構造函數(shù)后趁舀,vptr在指向子類的btbl。
- 父類指針(引用)指向子類進行多態(tài)調用時候祝沸,編譯器并不關系是子類還是父類赫编,而是通過vptr指向的btbl來找到對應的函數(shù)指針,并調用函數(shù)奋隶。
- vtbl由編譯器來維護
重載擂送、覆蓋、隱藏的區(qū)別和執(zhí)行方式
4.1成員函數(shù)被重載的特征
(1)相同的范圍(在同一個類中)唯欣;
(2)函數(shù)名字相同嘹吨;
(3)參數(shù)不同;
(4)virtual 關鍵字可有可無境氢。
4.2“覆蓋”是指派生類函數(shù)覆蓋基類函數(shù)蟀拷,特征是:
(1)不同的范圍(分別位于派生類與基類);
(2)函數(shù)名字相同萍聊;
(3)參數(shù)相同问芬;
(4)基類函數(shù)必須有virtual 關鍵字。
4.3“隱藏”是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù)寿桨,特征是:
(1)如果派生類的函數(shù)與基類的函數(shù)同名此衅,但是參數(shù)不同,此時亭螟,不論有無virtual關鍵字挡鞍,基類的函數(shù)將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數(shù)與基類的函數(shù)同名预烙,但是參數(shù)相同墨微,但是基類函數(shù)沒有virtual 關鍵字。此時扁掸,基類的函數(shù)被隱藏(注意別與覆蓋混淆)翘县。
小結:說白了就是如果派生類和基類的函數(shù)名和參數(shù)都相同,屬于覆蓋谴分,這是可以理解的吧锈麸,完全一樣當然要覆蓋了;如果只是函數(shù)名相同狸剃,參數(shù)并不相同掐隐,則屬于隱藏。
示例
class Parent {
public:
int x;
Parent(int x) {
this->x = x;
}
void print() {
cout << "Parent " << x << endl;
}
};
class Children : public Parent {
public:
Children(int x) : Parent(x) {
}
void print() {
cout << "Children " << x << endl;
}
};
int main() {
Parent *parent = NULL;
Parent p(1);
Children c(10);
parent = &p;
parent->print();
parent = &c;
parent->print();
}
測試一運行結果钞馁,發(fā)現(xiàn)雖然父類指針或引用指向了子類虑省,但是在調用方法時候還是調用的父類的方法
Parent 1
Parent 10
測試二,對print方法加上virtual關鍵字僧凰,這時才體現(xiàn)出多態(tài)
Parent 1
Children 10