多重继承和虚继承的问题

creamyjung 2008-10-15 10:53:35
看一段程序
#include <iostream.h>

class A
{
public:
int a;
};

class B
{
public:
int b;
};

class C: virtual public A,virtual public B
{
public:
int c;
};

class D: virtual public A,virtual public B
{
public:
int d;
};

class E: virtual public C,virtual public D
{
public:
int e;
};

void main()
{
cout<<sizeof(E)<<endl;
}
VC6运行结果是32
如果class E继承的时候去掉一个virtual,改成:
class E: virtual public C,public D
则运行结果变成28,为什么?
...全文
118 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
taodm 2008-10-16
  • 打赏
  • 举报
回复
真好奇这类问题,就先去看《深度探索C++对象模型》
jia_xiaoxin 2008-10-16
  • 打赏
  • 举报
回复
行结果是32 是因为派生类构造时在它的内存空间中需要包含它直接或间接的父类。
因为E虚基类继承自C和D,而C和D是虚基类继承A和B,那么按照C++语法,E将包含C和D,而C和D共享一份A和B,所以E也就包含一份A和B,连上E成员占用的空间,那么就是5*sizeof(int)
=20;别忘了,E,D,C都要生成各自的虚基类表的指针,所以结果为 20 + 3* 4 = 32;

如果class E继承的时候去掉一个virtual改成:
class E: virtual public C,public D
我觉的对E来说,之所以sizeof(E) = 28,这是一种优化,因为此时的E已经不再需要维护虚基类表指针。
class E: virtual public C,public D
class E: public C,public D
class E: public C,virtual public D
的结果都是一样的。



jackzhhuang 2008-10-15
  • 打赏
  • 举报
回复
当然这些东西依赖编译器。
jackzhhuang 2008-10-15
  • 打赏
  • 举报
回复
A——A.a四个字节
B——B.b四个字节
C——A.a+B.b+c+1个虚继承指针=16个字节
同理D位16个字节
E——A.a+B.b+C.c+D.d+e+1个虚继承指针(CD)+2个虚继承指针(AB)= 32

去掉virtual后,E直接继承D的虚继承指针就成了:
E——A.a+B.b+C.c+D.d+e+1个虚继承指针(CD)+1个虚继承指针(AB)= 28

解释:

首先明白虚继承就是为了节省空间,若两个类甲和乙共同虚继承一个丙类,那么再有一个类继承一般继承于甲和乙类时,只会为丙类分配一次内存。

然后我们知道,一个类里面如声明了一个虚函数,就会在编译时被编译器悄悄加入一个指向虚函数表的虚函数指针作为成员函数。
同样,一个类若是虚继承另一个类,这个时候编译的时候就会生成一个指向父类的虚继承指针,如果虚继承多个父类,则虚继承指针指向最左边那个父类,而后依次是其他父类。

这样C就是A.a + B.b + C.c + 一个虚继承指针 = 16个字节
E就是A.a + B.b + C.c + D.d + E.e + 一个指向C的虚继承指针 + 一个C的成员指针(指向A,这个指针是作为C的成员变量继承过来的)+一个D的指针(指向A,当然也是作为D的成员变量继承过来的)= 32个字节

去掉virtual后,E直接继承D,发现D于C共同虚继承于A和B,这样D的虚继承指针就没有了,由C的虚继承指针负责指向A,于是少了一个指针,就是28个字节了。

我是这么理解的。
creamyjung 2008-10-15
  • 打赏
  • 举报
回复
但是对与C或者D,继承自A和B的时候去掉一个virtual却不影响size大小
scklotz 2008-10-15
  • 打赏
  • 举报
回复
虚继承方式,需要用额外的空间来存放存取虚基类的信息.具体的实现方式依赖于编译器.
在vc下,你可以试试调试时切到汇编看看内存布局
frank_ll 2008-10-15
  • 打赏
  • 举报
回复
我是这样猜想的
当所有的继承方式都是虚继承时,在类中将维持一个指向虚继承表的指针,使运行时查找更快
如果其中去掉一个虚继承,那么将不维护这个指针

65,211

社区成员

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

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