多態分爲兩類
- 靜態多態: 函數重載 運算符重載,複用函數名。
- 動態多態: 派生類和虛函數運行時多態。
區別
靜態多態的函數地址早綁定: 編譯階段確定函數地址
動態多態的函數地址晚綁定: 運行階段確定函數地址
靜態多態經常見,這裏就不講了
動態多態滿足關係
- 存在繼承關係
- 子類重寫父類虛函數(虛函數 關鍵字 virtual)
- 父類指針或引用 執行子類對象
動態多態原理剖析
#include<iostream>
#include<string>
using namespace std;
class animal {
public:
virtual void speak() {//虛函數
cout << "我是小妖精" << endl;
}
};
class dog :public animal {
public:
void speak() {
cout << "我是小狗,汪汪汪!" << endl;
}
};
void test(animal& ani) {//父類通過引用執行子類對象
ani.speak();
}
int main() {
/*animal* f1 =new dog; //指針方式
f1->speak();
animal& f2 = stu;//引用方式
f2.speak();*/
dog stu;
test(stu); //我是小狗,汪汪汪! 引用方式
}
首先 虛函數會產生一個 vfptr(虛擬函數表指針) 然後虛擬函數指針會指向一個vttable(虛擬函數表)
vftable中儲存的是虛函數的地址 在子類繼承父類時會繼承父類的一切,包括vftable
而重寫子類對象會產生新的vftable去覆蓋子類中繼承的vftable
所以上述例子中
void test(animal& ani) {
ani.speak();
}
speak爲小狗叫聲而不是動物叫聲。