一、多态成立的條件
1、發生了類的繼承。
2、有virtual關鍵字實作虛函數重寫。
3、父類指針或引用指向了一個子類對象。
二、多态的原理
1、當類中聲明虛函數時,編譯器會自動在類中生成一個虛函數表。虛函數表是一個存儲類成員函數指針的資料結構,且有編譯器自動生成和維護。
2、所有在類中使用類virtual關鍵字的成員方法都會被放入該類的虛函數表中。
3、在定義對象時,當存在虛函數是,每一對象中都會擁有一個指向虛函數表的指針,是以C++編譯器不需要區分子對象或者父類對象,隻需要找到對象中的vptr指針所指向的虛函數表即可。(這個過程在動态聯編)
虛函數表的生成---每個類都會一個虛函數表
當我們傳入的是父類對象時:
父類對象傳入時,vptr指針作用方式
三、vptr指針什麼時候初始化
當我們在建立對象時,此時C++編譯器會給我們多配置設定幾個位元組記憶體,用來存放vptr指針,這個我們會在後面vptr的證明裡面說。
在對象建立時,由編譯器對VPTR指針進行初始化、隻有當對象的構造完全(子類對象構造時,還要構造繼承來的父類對象)結束後vptr的指針指向才會最終确定,父類對象的vptr指針指向父類的虛函數表,子類對象vptr指針指向父類的虛函數表。
是以在構造函數中調用虛函數,不會實作多态。vptr指針是分初始化的,先初始化父類的,在初始化子類的。
四、vptr指針存在的證明。
我們知道sizeof()用來求指定的變量的記憶體大小,我們可以定義一個隻有一個int類型的成員對象和一個虛函數的簡單類,在不考慮虛函數存在的情況下,我們知道這個類的對象所占有的記憶體大小為4個位元組。但是有虛函數時,就不是四個位元組,代碼實作如下:
class ParentA
{
public:
virtual void print() //使用了虛函數,會有vptr指針
{
cout << "I`m parentA..." << endl;
}
private:
int a;
};
class ParentB
{
public:
void print()
{
cout << "I`m parentB..." << endl;
}
private:
int a;
};
int main()
{
ParentA AP;
ParentB BP;
cout << "sizeof(AP):" << sizeof(AP) << endl;
cout << "sizeof(BP):" << sizeof(BP) << endl;
system("pause");
return 0;
}
輸出:
sizeof(AP):8
sizeof(BP):4
請按任意鍵繼續. . .
如上,我們發現C++編譯器确實會給有虛函數的對象多配置設定4分位元組的記憶體,用來存放vptr指針。