虛函數——虛表總結


非虛擬繼承
ide

帶虛函數的類函數

class Baseui

{spa

public:對象

virtual void FunTest1()blog

{繼承

cout<<"Base::FunTest1()"<<endl;get

}編譯器

 

virtual void FunTest2()it

{

cout<<"Base::FunTest2()"<<endl;

}

 

int _data1;

};

 

int main()

{

Base b;

b._data1 = 0x01;

return 0;

}

 

Base類沒有顯式定義本身的構造函數,此時編譯器會和成默認的構造函數,

wKioL1cTFxaCBRLgAAAoR3gfVbk895.png

合成的構造函數中主要完成在對象頭4個字節中填寫虛表地址:

wKioL1cTF8bBwdDSAABzWVmXBKg654.png

Base類對象最後的模型以下:

wKioL1cTGAGwO-38AABSC0LdyZY885.png

注意:同一個類的對象共用同一個虛表

wKiom1cTF4vzHqqkAABHdbNhbx0424.png

從上述的結果中能夠獲得印證。

【單繼承(派生類中沒有虛函數覆蓋)

class Base

{

public:

virtual void FunTest1()

{cout<<"Base::FunTest1()"<<endl;}

 

virtual void FunTest2()

{cout<<"Base::FunTest2()"<<endl;}

           int _data1;

};

 

class Derive:public Base

{

public:

virtual void FunTest3()

{cout<<"Derive::FunTest3()"<<endl;}

 

virtual void FunTest4()

{cout<<"Derive::FunTest4()"<<endl;}

 int _data2;

};

 

// 打印虛表

typedef void (*VtbFun)();

void PrintVtable()

{

cout<<"Derive類的虛函數表:"<<endl;

Derive d1;

d1._data1 = 0x01;

d1._data2 = 0x02;

 

int* pVTable = (int*)*(int*)&d1;

VtbFun FunTest = (VtbFun)*pVTable;

while(NULL != FunTest)

{

FunTest();

cout<<(int*)FunTest<<endl;

pVTable += 1;

FunTest = (VtbFun)*pVTable;

}

 

cout<<"虛表結束:"<<endl;

}

 

int main()

{

Base b1;

Derive d1;

return 0;

}

 

按照如上分析的順序,探索下單繼承下派生類對象模型以及虛表

首先看看編譯器爲派生類合成的缺省構造函數:

wKiom1cTF-Wh24hbAAAgNM6iSH4165.png

派生類構造函數中進行了以下事情:

wKioL1cTGOTAwrtAAABwJABaUjA974.png

Derive d1;

d1._data1 = 0x01;

d1._data2 = 0x02;

派生類最後的對象模型爲:

wKiom1cTGHLx5AaQAAB-F8t8vIE753.png

【單繼承(派生類中有虛函數覆蓋)

class Base

{

public:

virtual void FunTest1()

{

cout<<"Base::FunTest1()"<<endl;

}

 

virtual void FunTest2()

{

cout<<"Base::FunTest2()"<<endl;

}

 

int _data1;

};

 

class Derive:public Base

{

public:

virtual void FunTest1()

{

cout<<"Derive::FunTest1()"<<endl;

}

 

virtual void FunTest3()

{

cout<<"Derive::FunTest3()"<<endl;

}

 

virtual void FunTest4()

{

cout<<"Derive::FunTest4()"<<endl;

}

int _data2;

};

 

int main()

{

PrintVtable();

return 0;

}

 

派生類對象模型及虛表建議規則:

wKioL1cTGXHS1JmbAAB4oVf1y-0848.png

【多繼承(派生類不覆蓋基類虛函數)

class Base

{

public:

virtual void FunTest1()

{

cout<<"Base::FunTest1()"<<endl;

}

 

virtual void FunTest2()

{

cout<<"Base::FunTest2()"<<endl;

}

 

int _data1;

};

 

class Base1

{

public:

virtual void FunTest3()

{

cout<<"Base1::FunTest3()"<<endl;

}

 

virtual void FunTest4()

{

cout<<"Base1::FunTest4()"<<endl;

}

 

int _data2;

};

 

class Derive:public Base, public Base1

{

public:

virtual void FunTest5()

{

cout<<"Derive::FunTest5()"<<endl;

}

 

int _data3;

};

 

int main()

{

cout<<"sizeof(Derive) = "<<sizeof(Derive)<<endl;

Derive d;

d._data1 = 0x01;

d._data2 = 0x02;

d._data3 = 0x03;

PrintVtable();

return 0;

}

 

一樣:看看編譯器合成的派生類的對象作了什麼工做

wKioL1cTGg-iUjxSAACQVouVVX8725.png

觀察下派生類的對象模型和虛表的創建過程

wKioL1cTGkqSnByhAACaupSc5hM060.png

從上面的結果能夠看出,Derive類本身特有的虛函數直接添加在Base類對應虛函數表最後的位置,你們可將BaseBase1的順序交換驗證下。

 

【多繼承(派生類覆蓋基類虛函數)

class Base

{

public:

virtual void FunTest1()

{

cout<<"Base::FunTest1()"<<endl;

}

 

virtual void FunTest2()

{

cout<<"Base::FunTest2()"<<endl;

}

 

int _data1;

};

 

class Base1

{

public:

virtual void FunTest3()

{

cout<<"Base1::FunTest3()"<<endl;

}

 

virtual void FunTest4()

{

cout<<"Base1::FunTest4()"<<endl;

}

 

int _data2;

};

 

// 此次將繼承列表中BaseBase1的位置互換

class Derive:public Base1, public Base

{

public:

virtual void FunTest1()

{

cout<<"Derive::FunTest1()"<<endl;

}

virtual void FunTest3()

{

cout<<"Derive::FunTest3()"<<endl;

}

virtual void FunTest5()

{

cout<<"Derive::FunTest5()"<<endl;

}

 

int _data3;

};

 

int main()

{

           PrintVtable();

return 0;

}

 

此時派生類的對象模型和虛表的結構:

wKioL1cTGuuy0qP-AACM_L5u75o513.png

虛擬繼承

// 沒有虛函數覆蓋,但派生類有本身的虛函數

class Base

{

public:

virtual void FunTest1()

{

cout<<"Base::FunTest1()"<<endl;

}

 

virtual void FunTest2()

{

cout<<"Base::FunTest2()"<<endl;

}

 

int _data1;

};

 

class Derive:virtual public Base

{

public:

virtual void FunTest3()

{

cout<<"Derive::FunTest3()"<<endl;

}

virtual void FunTest4()

{

cout<<"Derive::FunTest4()"<<endl;

}

 

int _data2;

};

 

虛擬繼承編譯器爲派生類合成的默認構造函數分析

wKiom1cTGoaBxFOQAAAtU05EoKw035.png

編譯器爲派生類合成的默認構造函數任務分析:

wKiom1cTGsKxV8-bAACQu_Sym_4528.pngwKiom1cTGvLCLl5lAABYum-15Ac313.png

虛擬繼承派生類對象模型分析

wKioL1cTG-uiUVZJAAB97eWBdGc584.png

相關文章
相關標籤/搜索