[C++对象模型][9]虚继承与虚函数表
生活随笔
收集整理的這篇文章主要介紹了
[C++对象模型][9]虚继承与虚函数表
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一 虛繼承
1) 代碼:
Code#include?<iostream>
using?namespace?std;
class?B
{
public:
????int?i;
????virtual?void?vB(){?cout?<<?"B::vB"?<<?endl;?}
????void?fB(){?cout?<<?"B::fB"?<<?endl;}
};
class?D1?:?virtual?public?B
{
public:
????int?x;
????virtual?void?vD1(){?cout?<<?"D1::vD1"?<<?endl;?}
????void?fD1(){?cout?<<?"D1::fD1"?<<?endl;}
};
class?D2?:?virtual?public?B
{
public:
????int?y;
????void?vB(){?cout?<<?"D2::vB"?<<?endl;}
????virtual?void?vD2(){?cout?<<?"D2::vD2"?<<?endl;}
????void?fD2(){?cout?<<?"D2::fD2"?<<?endl;}
};
class?GD?:??public?D1,?public?D2
{
public:
????int?a;
????void?vB(){?cout?<<?"GD::vB"?<<?endl;}
????void?vD1(){cout?<<?"GD::vD1"?<<?endl;}
????virtual?void?vGD(){cout?<<?"GD::vGD"?<<?endl;}
????void?fGD(){cout?<<?"GD::fGD"?<<?endl;}
};
?
?
2)類圖:
?
3)VS2008的編譯選項查看布局:
?
4)可視化表示:
?
5)代碼驗證:(此時的虛函數表不是以NULL結尾,為什么?)
Codetypedef?void?(*Fun)();
void?PrintMember(int?*pI)
{
????cout?<<?*pI?<<?endl?<<?endl;
}
void?PrintVT(int?*pVT)
{
????while(*pVT?!=?NULL)
????{
????????(*(Fun*)(pVT))();
????????pVT++;
????}
}
void?PrintMemberAndVT(GD?*pGD)
{
????int?*pRoot?=?(int*)pGD;
????int?*pD1VT?=?(int*)*(pRoot?+?0);?
????(*(Fun*)(pD1VT))();?(*(Fun*)(pD1VT?+1))();
????int?*pVB?=?(int*)*(pRoot?+1);??cout?<<?"vbtable's?adress:"?<<?*pVB?<<?endl;
????int?*pX?=?(pRoot?+?2);?PrintMember(pX);
????int?*pD2VT?=?(int*)*(pRoot?+?3);?
????(*(Fun*)(pD2VT))();
????int?*pVB2?=?(int*)*(pRoot?+4);?cout?<<?"vbtable's?adress:"?<<?*pVB2?<<?endl;
????int?*pY?=?(pRoot?+?5);?PrintMember(pY);
????int?*pA?=?(pRoot?+?6);?PrintMember(pA);
????int?*pBVT?=?(int*)*(pRoot?+?7);?
????(*(Fun*)(pBVT))();
????int?*pI?=?(pRoot?+?8);?PrintMember(pI);
}
void?TestVT()
{
????B?*pB?=?new?GD();
????GD?*pGD?=?dynamic_cast<GD*>(pB);
????pGD->i?=?10;
????pGD->x?=?20;
????pGD->y?=?30;
????pGD->a?=?40;
????PrintMemberAndVT(pGD);
????delete?pGD;
}
?
6)驗證代碼結果:
?
7)總結:
虛繼承,使公共的基類在子類中只有一份,我們看到虛繼承在多重繼承的基礎上多了vbtable來存儲到公共基類的偏移。
?
二 虛繼承運行時類型轉化
?
1)代碼驗證:
?
Codevoid?TestDynamicCast()
{
????B?*pB?=?new?GD();
????GD?*pGD?=?dynamic_cast<GD*>(pB);
????cout?<<?"GD:"?<<?pGD?<<?endl;
????D1?*pD1?=?dynamic_cast<D1*>(pB);
????cout?<<?"D1:"?<<?pD1?<<?endl;
????D2?*pD2?=?dynamic_cast<D2*>(pB);
????cout?<<?"D2:"?<<?pD2?<<?endl;
????cout?<<?"B:"?<<?pB?<<?endl;
}
?
?
2)驗證代碼結果:
?
3)總結:
還是從內存布局來看dynamic_cast時地址的變化,第一個基類的地址與子類相同,其他的基類和虛基類需要做偏移。
三 完!
轉載于:https://www.cnblogs.com/itech/archive/2009/03/01/1399996.html
總結
以上是生活随笔為你收集整理的[C++对象模型][9]虚继承与虚函数表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于MSSQL存储过程中使用游标的一个小
- 下一篇: C++虚函数表解析(转) ——写的真不错