1.虛函數,在函數前加virtual即可。有虛函數時,父類指針指向父類對象時就會使用父類的成員,指向子類對象時就可以使用子類成員,進而我們引入了多態的概念。
2.多態:父類指針指向子類的對象,通過父類指針調用子類函數,使其具有多種形態。
2.1.實現多態的必要條件:
? ? ? ? 1.存在繼承關系
? ? ? ? 2.父類中有虛函數
? ? ? ? 3.在子類中對父類虛函數進行了重寫
? ? ? ? 4.存在父類指針,并通過該指針調用虛函數
2.2.多態的實現原理:
? ? ? ? 1.父類的虛函數在子類中重寫
? ? ? ? 2.對象的前四個或八個字節是一個虛指針(vptr)
? ? ? ? 3.所有的虛函數地址組成一個虛函數列表(vTable)(本質:函數指針數組)
? ? ? ? 4.虛指針指向虛函數列表
? ? ? ? 5.在子類中重寫的虛函數地址會覆蓋掉繼承來的虛函數列表中的對應函數的地址
? ? ? ? 6.當調用函數時根據當前虛函數列表,決定執行哪一個具體的函數
2.3.多態的優點表現在它能提高復用性和拓展性,它的缺點體現在空間,效率以及安全性上。
3.純虛函數,例如:
virtual void show() = 0
包含純虛函數的類稱為抽象類,抽象類不允許實例化,子類中必須對純虛函數重寫。
所有函數都是純虛函數的類叫作接口類。
在使用多態時我們要注意一個問題,如下
#include<iostream>
using namespace std;class Father
{
public:Father(){cout << "Father" << endl;}~Father(){cout << "~Father" << endl;}
};class Son:public Father
{
public:Son(){cout << "Son" << endl;}~Son(){cout << "~Son" << endl;}
};int main()
{Father* p = new Son;delete p;return 0;
}
當我們執行此段代碼
我們會發現它并沒有執行子類的析構函數,會造成內存泄露問題。
為解決此問題我們就要在父類中使用虛析構,即可解決問題。
virtual ~Father()
{cout << "~Father" << endl;
}
注:沒有虛構造,有虛析構。