非虛擬繼承
公司主營業(yè)務(wù):網(wǎng)站設(shè)計(jì)制作、網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出大化免費(fèi)做網(wǎng)站回饋大家。
【帶虛函數(shù)的類】
class Base
{
public:
virtual void FunTest1()
{
cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; int main() { Base b; b._data1 = 0x01; return 0; } Base類沒有顯式定義自己的構(gòu)造函數(shù),此時(shí)編譯器會(huì)和成默認(rèn)的構(gòu)造函數(shù), 合成的構(gòu)造函數(shù)中主要完成在對(duì)象頭4個(gè)字節(jié)中填寫虛表地址: Base類對(duì)象最后的模型如下: 注意:同一個(gè)類的對(duì)象共用同一個(gè)虛表 從上述的結(jié)果中可以得到印證。 【單繼承(派生類中沒有虛函數(shù)覆蓋)】 class Base { public: virtual void FunTest1() {cout<<"Base::FunTest1()"< virtual void FunTest2() {cout<<"Base::FunTest2()"< int _data1; }; class Derive:public Base { public: virtual void FunTest3() {cout<<"Derive::FunTest3()"< virtual void FunTest4() {cout<<"Derive::FunTest4()"< int _data2; }; //打印虛表 typedef void (*VtbFun)(); void PrintVtable() { cout<<"Derive類的虛函數(shù)表:"< Derive d1; d1._data1 = 0x01; d1._data2 = 0x02; int* pVTable = (int*)*(int*)&d1; VtbFun FunTest = (VtbFun)*pVTable; while(NULL != FunTest) { FunTest(); cout<<(int*)FunTest< pVTable += 1; FunTest = (VtbFun)*pVTable; } cout<<"虛表結(jié)束:"< } int main() { Base b1; Derive d1; return 0; } 按照如上分析的順序,探索下單繼承下派生類對(duì)象模型以及虛表 首先看看編譯器為派生類合成的缺省構(gòu)造函數(shù): 派生類構(gòu)造函數(shù)中進(jìn)行了如下事情: Derive d1; d1._data1 = 0x01; d1._data2 = 0x02; 派生類最后的對(duì)象模型為: 【單繼承(派生類中有虛函數(shù)覆蓋)】 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Derive:public Base { public: virtual void FunTest1() { cout<<"Derive::FunTest1()"< } virtual void FunTest3() { cout<<"Derive::FunTest3()"< } virtual void FunTest4() { cout<<"Derive::FunTest4()"< } int _data2; }; int main() { PrintVtable(); return 0; } 派生類對(duì)象模型及虛表建議規(guī)則: 【多繼承(派生類不覆蓋基類虛函數(shù))】 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Base1 { public: virtual void FunTest3() { cout<<"Base1::FunTest3()"< } virtual void FunTest4() { cout<<"Base1::FunTest4()"< } int _data2; }; class Derive:public Base, public Base1 { public: virtual void FunTest5() { cout<<"Derive::FunTest5()"< } int _data3; }; int main() { cout<<"sizeof(Derive) = "< Derive d; d._data1 = 0x01; d._data2 = 0x02; d._data3 = 0x03; PrintVtable(); return 0; } 同樣:看看編譯器合成的派生類的對(duì)象做了什么工作 觀察下派生類的對(duì)象模型和虛表的建立過程 從上面的結(jié)果可以看出,Derive類自己特有的虛函數(shù)直接添加在Base類對(duì)應(yīng)虛函數(shù)表最后的位置,大家可將Base和Base1的順序交換驗(yàn)證下。 【多繼承(派生類覆蓋基類虛函數(shù))】 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Base1 { public: virtual void FunTest3() { cout<<"Base1::FunTest3()"< } virtual void FunTest4() { cout<<"Base1::FunTest4()"< } int _data2; }; //這次將繼承列表中Base和Base1的位置互換 class Derive:public Base1, public Base { public: virtual void FunTest1() { cout<<"Derive::FunTest1()"< } virtual void FunTest3() { cout<<"Derive::FunTest3()"< } virtual void FunTest5() { cout<<"Derive::FunTest5()"< } int _data3; }; int main() { PrintVtable(); return 0; } 此時(shí)派生類的對(duì)象模型和虛表的結(jié)構(gòu): 虛擬繼承 //沒有虛函數(shù)覆蓋,但派生類有自己的虛函數(shù) class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Derive:virtual public Base { public: virtual void FunTest3() { cout<<"Derive::FunTest3()"< } virtual void FunTest4() { cout<<"Derive::FunTest4()"< } int _data2; }; 虛擬繼承編譯器為派生類合成的默認(rèn)構(gòu)造函數(shù)分析 編譯器為派生類合成的默認(rèn)構(gòu)造函數(shù)任務(wù)分析: 虛擬繼承派生類對(duì)象模型分析
文章標(biāo)題:虛函數(shù)——虛表總結(jié)
轉(zhuǎn)載注明:http://weahome.cn/article/jhojsg.html