天天看點

C++複習筆記(四)之多态實作的本質

一、多态成立的條件

1、發生了類的繼承。

2、有virtual關鍵字實作虛函數重寫。

3、父類指針或引用指向了一個子類對象。

二、多态的原理

1、當類中聲明虛函數時,編譯器會自動在類中生成一個虛函數表。虛函數表是一個存儲類成員函數指針的資料結構,且有編譯器自動生成和維護。

2、所有在類中使用類virtual關鍵字的成員方法都會被放入該類的虛函數表中。

3、在定義對象時,當存在虛函數是,每一對象中都會擁有一個指向虛函數表的指針,是以C++編譯器不需要區分子對象或者父類對象,隻需要找到對象中的vptr指針所指向的虛函數表即可。(這個過程在動态聯編)

C++複習筆記(四)之多态實作的本質

虛函數表的生成---每個類都會一個虛函數表

C++複習筆記(四)之多态實作的本質

當我們傳入的是父類對象時:

C++複習筆記(四)之多态實作的本質

父類對象傳入時,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指針。

繼續閱讀