#include <iostream>
class SuperBase
{
public:
int Sb;
};
class Base1:virtual public SuperBase
{
public:
int a;
};
class Base2:virtual public SuperBase
{
public:
int b;
};
class Derived: public Base1,public Base2
{
public:
int c;
};
int main()
{
using namespace std;
cout<<sizeof(Derived);
return 0;
}
output is showing 24
but it should show 20 because
int sb 4 bytes
int a 4 bytes
int b 4 bytes
int c 4 bytes
vbptr 4 bytes
total 20 bytes
因为我们使用虚拟继承概念,所以 int sb 不应该计算两次,不是吗?
24 可能是:
- 4 for Sb
- 4 for a
- 4 for b
- 4 for c
- 8 为虚拟继承的开销。
在我的(32 位)编译器上,sizeof(Derived)
是 24 且sizeof(Base1)
不过,是 12,这表明开销不是always 8.
我猜测 8 由 Base1 子对象开头的一个 vtable(或类似)指针和 Base2 子对象中的另一个指针组成,当指向该对象的指针被转换为Base2*
。多重继承的问题是 Base1 距对象开头的偏移量不能与 Base2 距对象开头的偏移量相同。
特别是,这意味着对于 Base1 和 Base2 之一,其作为 Derived 的基类子对象时的偏移量与 BaseN 是最底层派生类时的偏移量不同。但是,当您转换为 Base2* 时,结果值必须指向“看起来像”Base2 的值。因此,在虚拟继承实际上导致共享基类的情况下,会产生一些额外的开销。
另一种方法就是做sizeof(SuperBase)
4, sizeof(Base1)
and sizoef(Base2)
都是 12(两个 int 和一个 vtable 指针),并且sizeof(Derived)
等于 28:Sb 为 4 个,a、b、c 各 4 个,三个 vtable 指针各 4 个,Base1、Base2 和 Derived 各一个。但是你的编译器(我认为)帮了你一个忙,并将 Derived 的 vtable 指针安排在与 Base1 相同的位置,就像单继承的正常情况一样。
在所有情况下,当我说“vtable指针”时,它可能与用于虚拟函数的东西完全相同,也可能不完全相同,但它是某种类元数据。也许它只是用于到达基类的指针或偏移量。
我在这里画了一些可能有帮助的小图表:
为什么不能在 C++ 中的非 POD 结构上使用 offsetof? https://stackoverflow.com/questions/1129894/why-cant-you-use-offsetof-on-non-pod-strucutures-in-c/1130760#1130760
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)