日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

[C++对象模型][9]虚继承与虚函数表

發布時間:2025/3/13 c/c++ 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [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結尾,為什么?

Code
typedef?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)代碼驗證:

?

Code
void?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]虚继承与虚函数表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。