为了避免出现菱形问题,用使用虚拟继承后的子类大问题?

铭毅天下
大数据领域优质创作者
博客专家认证
2012-08-29 07:42:38
为了避免出现菱形问题,用使用虚拟继承后的子类大小。示例如下:
class baseClass
{
public:
virtual void fool(void) {}
int nValue;
char c;
};

class midClass1 : virtual public baseClass
{
public:
virtual void setVal(){}
int nMidValue1;
};

class midClass2 : virtual public baseClass
{
public:
virtual void setVal(){}
int nMidValue2;
};

class derivedClass : public midClass1, public midClass2
{
public:
virtual void foo2(){}
int subVal;
};
int main()
{
cout << sizeof(baseClass) << endl; //12
cout << sizeof(midClass1) << endl; //24
cout << sizeof(midClass2) << endl; //24
cout << sizeof(derivedClass) << endl; //48
return 0;
}
已经知道的,对于baseClass类的大小,考虑地址对齐为4(c)+4(nvalue)+4(虚拟函数指针)共12个字节;
如果去掉虚拟继承,为如下形式:
class midClass1 : public baseClass //仅是增加了nMidValue1,扩展为16字节
class midClass2 : public baseClass //仅是增加了nMidValue2,扩展为16字节
class derivedClass : public midClass1, public midClass2 // 在继承midclass1,midclass2基础上仅是增加了subVal,为16+16+4=36字节。
不理解点:为什么加了虚拟继承,sizeof(midClass1) = 24;sizeof(midClass2)=24;sizeof(derivedClass)48;
如何解读?
主要原因,VisualC++添加了了虚拟基类表指针来实现虚拟继承,因此,空间变大?但感觉应该增加4个字节的指针值,实际怎么多了8个字节?不解中。。。。。。。
...全文
250 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Leon- 2012-09-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
不要浪费生命讨论虚继承时的内存模型。
因为和编译太高度相关了。甚至同一个编译器内都会在不同的条件下使用不同的模型。
珍惜生命吧。
[/Quote]
en,vs2005上 我的结果是12 24 24 40
铭毅天下 2012-09-04
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

不要浪费生命讨论虚继承时的内存模型。
因为和编译太高度相关了。甚至同一个编译器内都会在不同的条件下使用不同的模型。
珍惜生命吧。
[/Quote]
谢谢提醒,主要应对面试,也为编程更深基础。
taodm 2012-09-04
  • 打赏
  • 举报
回复
不要浪费生命讨论虚继承时的内存模型。
因为和编译太高度相关了。甚至同一个编译器内都会在不同的条件下使用不同的模型。
珍惜生命吧。
铭毅天下 2012-09-04
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

baseClass是12个字节(虚函数表,两个成员)
midClass1 和midClass2一样,他们包含了baseClass(12个字节),虚函数表(4个字节),1个成员(4个字节),一个指向虚基类表(4个字节),一共24个字节
derivedClass包括derivedClass(12个字节),midClass1(除开baseClass还有12个字节),midClass2(12个字节)……
[/Quote]

谢谢你,我修正了下你的答案:

解读:baseClass类包含1个虚函数表指针(4个字节)、1个int型数据成员(4个字节)、1个char型数据(对齐后4个字节)成员,共12个字节。
midClass1同midClass2一致,需要在baseClass类的基础上,多了1个虚函数表指针(4个字节)、1个指向虚基类表的指针(4个字节)、一个整形数据成员(4个字节),合计共12+12 =24个字节。
derivedClass 在上述的基础上,包含baseClass(12个字节)、midClass1(新增12个字节)、midClass2(新增12个字节)、derivedClass的1个整形数据成员(4个字节),合计共40个字节。注意derivedClass是继承而非虚拟继承自两个父类,所以没有指向虚基类表的指针。
扩展,如果将上述继承该为:class derivedClass : virtual public midClass1, virtual public midClass2.上述大小会变为48个字节(多了两个指向虚基类表的指针(每个4个字节))。
class derivedClass : virtual public midClass1, public midClass2. 会不会有这种只有一个虚拟继承的情况,如何解释呢?我调试了还是40个字节。他不需要只想虚基类表的指针吗?与你探讨下。。。
yuanlianxi03 2012-09-03
  • 打赏
  • 举报
回复
在虚基类中,最终继承的每个基类中都会包含一个指向他们共有基类数据成员的一个指针,midclass1,midclass2中各含一个指向共有基类baseClass数据成员的指针;刚好多出了两个指针的内存
Corner 2012-09-03
  • 打赏
  • 举报
回复
baseClass是12个字节(虚函数表,两个成员)
midClass1 和midClass2一样,他们包含了baseClass(12个字节),虚函数表(4个字节),1个成员(4个字节),一个指向虚基类表(4个字节),一共24个字节
derivedClass包括derivedClass(12个字节),midClass1(除开baseClass还有12个字节),midClass2(12个字节),一个成员变量(4个字节),一共40个字节(LZ应该写错了),其中derivedClass的虚函数指针会被放在第一个基类的虚表中(midClass1,且是继承来的基类,而不是虚继承),所以不占内存。
铭毅天下 2012-09-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

你的类中只要有visual函数就会产生这个vtb和一个vptr。它们都会占内存的。
[/Quote]

不好意思,这么几天没有回帖。
那有vptr应该增加了4个字节,而实际为什么多了8个节呢?
漫步者、 2012-08-29
  • 打赏
  • 举报
回复
你的类中只要有visual函数就会产生这个vtb和一个vptr。它们都会占内存的。

64,266

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧