c 中虛函式繼承,虛表剖析

2021-07-24 15:54:58 字數 2973 閱讀 6541

虛表概念:

對於有虛函式類,編譯器都會維護一張虛表,物件的前四個位元組就是指向虛表的指標。虛表中存放的是虛函式的位址。虛函式按照其宣告順序存放在虛表中。在派生類中,前面是繼承基類的虛函式,若派生類重寫了基類中的虛函式則替換為重寫後的,派生類自己的虛函式追加在其後。如果派生類繼承了兩個基類,則派生類自己的虛函式追加到第乙個繼承的基類的虛表的後面。

單繼承(沒有重寫基類的虛函式)

class base

virtual void funtest2()

int _data1;

};class drived :public base

virtual void funtest4()

int _data2;

};typedef void(*vfp)();

void printvtp()//列印虛表

在派生類中,前面是基類的虛函式,後面是派生類的虛函式

單繼承(重寫基類的虛函式)

class base

virtual void funtest2()

int _data1;

};class drived :public base

virtual void funtest3()

int _data2;

};測試結果:

由於只重寫了基類的funtest1,所以虛表中列印了派生類重寫的funtest1與基類的funtest2,再加上派生類本身的虛函式。

派生類虛表的形成: a.先拷貝基類的虛表 

b.如果派生類重寫了基類的虛函式,則修改同位置的基類虛函式

c.跟上派生類新定義的虛函式

呼叫虛表:通過基類的引用或指標呼叫虛函式時,呼叫基類還是派生類的虛函式,

要根據執行時引用或指標的實際指向的型別確定。

單繼承的派生類的大小:虛表+ 基類的資料成員 + 派生類的成員

多繼承(無重寫)

class base1

virtual void funtest1()

virtual void funtest2()

int _data1;

};class base2

virtual void funtest3()

virtual void funtest4()

int _data2;

};class drived:public base1,public base2

virtual void funtest5()

virtual void funtest6()

int _data3;

};typedef void(*vfp)();

void printvtp()//列印虛表

base1 b1;

fun = (vfp*)*(int*)&b1;

cout << endl;

cout << "base1虛表" << endl;

while (*fun)

base2 b2;

fun = (vfp*)*(int*)&b2;

cout << endl;

cout << "base2虛表" << endl;

while (*fun)

}int main()

測試結果:

如果子類有新定義的虛函式,則放在繼承順序第一的基類虛表的後面(可看上圖測試結果)

菱形繼承(有重寫)

class base

virtual void funtest1()

int _data1;

};class c1 :public base

virtual void funtest1()

virtual void funtest2()

int _data2;

};class c2 :public base

virtual void funtest1()

virtual void funtest3()

int _data3;

};class derived :public c1, public c2

virtual void funtest1()

virtual void funtest2()

virtual void funtest3()

virtual void funtest4()

int _data4;

};typedef void(*vfp)();

void printvtp()//列印虛表

c2&c2 = d;

fun = (vfp*)*(int*)&c2;

cout << endl;

cout << "c2虛表" << endl;

while (*fun)

}int main()

測試結果:

說明: 如果派生類derived有新的虛函式,則新增到第一繼承順序的基類c1的虛表後面

該菱形繼承存在二義性,c1和c2中都繼承了base的成員變數

菱形繼承的大小:28   c1((虛表指標+base成員+c1成員 )==(12)) + c2(12) + 派生類d的成員(4)

虛函式 虛繼承 C

關於虛表,我們就要用到乙個關鍵字 virtual,可以修飾函式,也可以修飾類。類的成員函式被virtual修飾之後,就成為了虛函式 修飾類,主要是虛繼承。在此之前,我們首先要了解乙個概念 物件模型,也就是說,乙個基類形成之後,裡面的成員是怎麼存放的,當派生類繼承基類之後,派生類的成員是怎麼存放的。我...

c 虛函式和虛繼承

c 中,多型的實現需要虛函式,而虛函式主要包括兩部分,虛函式指標和虛函式表。基類將自己的一些函式設為虛函式,子類則需要在繼承基類後,重寫或者直接使用從基類的繼承下來的虛函式。基類自己會儲存乙份虛函式表,這個虛函式表含有指向基類虛函式的虛函式指標。當子類繼承基類後,同樣會將基類的虛函式表繼承下來,這樣...

虛函式 虛繼承

include using namespace std class a class b public a class c public b int main 結果是 4,4,4 為什麼?一,在private,protect,public的實際繼承中,派生類和基類擁有相同的虛函式表。但如果是虛繼承,會...