多型的現象及本質剖析(一)
阿新 • • 發佈:2019-01-29
多型的現象,同樣的呼叫語句有著不同的表現形態。
#include <iostream>
using namespace std;
class animal
{
public:
virtual void func() = 0;//純虛擬函式
protected:
private:
//char *voice = "我是annimal怎麼叫?";
};
class duck:public animal
{
public:
virtual void func()//純虛擬函式重寫
{
cout << voice << endl;
}
protected :
private:
char *voice = "我是鴨子,嘎嘎嘎";
};
class cat:public animal
{
public:
virtual void func()//純虛擬函式重寫
{
cout << voice << endl;
}
protected:
private:
char *voice = "我是小貓,喵喵喵";
};
//框架
void cry(animal *p)//賦值相容性原則,可傳遞子類指標
{
p->func();
}
int main()
{
duck d1;
cat c1;
cry(&d1);//執行效果:我是鴨子,嘎嘎嘎
cry(&c1);//執行效果:我是小貓,喵喵喵
system("pause");
return 0;
}
上例中同樣是呼叫cry()函式,不同的物件傳入,可以呼叫各自物件中的方法,產生不同的現象。這個現象便是多型。
從上述程式碼中可以總結出多型產生的條件有三個:
1、父類子類繼承關係。
2、(純)虛擬函式重寫。
3、父類指標(引用)指向子類物件。
virtual關鍵字,告訴編譯器這個函式要支援多型;不要根據指標型別判斷如何呼叫;而是要根據指標所指向的實際物件型別來判斷如何呼叫。
C++多型實現原理:
當類中宣告(純)虛擬函式時,編譯器會在類中生成一個虛擬函式表
虛擬函式表是一個儲存類成員函式指標的資料結構
虛擬函式表是由編譯器自動生成與維護的
virtual成員函式會被編譯器放入虛擬函式表中
存在虛擬函式時,每個物件中都有一個指向虛擬函式表的指標(vptr指標)
拿上述程式碼duck類來說,編譯的時候,編譯器會自動為duck加上一個VPTR指標,duck當執行d1類初始化的時候,編譯器就會自動建立一個d1的虛擬函式表,存放d1的func函式指標,而VPTR也會指向這個虛擬函式表。