这将非常依赖于平台,但我认为我们可以理解发生了什么。
首先,标准没有指定如何实现虚拟继承。就标准而言,甚至没有像 vtable 这样的东西。
ABCDerived
有BBase
和CBase
每一个都由一个int
. 还有一个实例ABase
由int
. 最后有一个 vtable ptr。
an 的大小int
取决于平台——它不一定是 4 个字节。但是如果我们假设它是 4 个字节,并且 vtable 的大小也是 4 个字节,我们有:
int [ABCDerived] = 4 bytes
int [CBase] = 4 bytes
int [BBase] = 4 bytes
int [ABase] = 4 bytes
vtable = 4 bytes
-------------
20 bytes
然而,这并不意味着sizeof (ABCDerived)
是 20。对齐也在这里发挥作用。该标准允许编译器增加对象的大小,以便该大小可以被多个整字整除。
考虑:
class ABase{
int iMem;
};
class BBase : public virtual ABase {
int iMem;
};
class CBase : public virtual ABase {
int iMem;
};
class ABCDerived : public BBase, public CBase {
int iMem;
};
int main()
{
ABCDerived d;
BBase& b = d;
ABase* ab = &b;
CBase& c = d;
ABase* ac = &b;
cout << hex << (void*) ab << "\n"
<< hex << (void*) ac << "\n";
cout << sizeof (d) << "\n" << sizeof (int) << "\n";
}
输出28
在我的 64 位 Linux 机器上。
但是,如果我打开打包(使用平台相关的#pragma 开关):
#pragma pack (1)
输出现在是 20。
所以,这一切的长短是:
这里有大量依赖于平台的东西。您不能说对象的大小是这样或那样,至少在不使用更多依赖于平台的东西并且不知道您的编译器如何实际实现虚拟继承的情况下。它的大小是它的大小。