我们定义如下的类继承关系:

class X {};
class Y: public virtual X {};
class Z: public virtual X {};
class A: public Y, public Z {};

这是一个菱形继承,且所有类都未定义数据成员。对他们计算sizeof(),书中给出以下结果:

Size of X: 1
Size of Y: 8
Size of Z: 8
Size of A: 12

X是一个空类,但sizeof(X)不等于0,而是1,这是编译器安插进去额一个byte,这保证了X的实例在内存中拥有地址:

X a, b;
if(&a == &b) cerr << "yipes!" << endl;

YZ的大小都是8。这个大小取决于三个因素

  1. 语言本身造成的overhead。C++支持virtual base class,会有一些额外负担。在派生类中,这个额外负担体现在某种形式的指针上,这个指针或者指向virtual base class subobject,或者指向一个表格,表格可能存放virtual base class subobject的地址,也可能存放其offset。该例中这个指针的大小为4字节(显然书中的环境是32位)。
  2. 编译器对于特殊情况提供的优化处理X的一个字节也出现在YZ上,传统上会被放在子类固定部分的末尾。某些编译器会对empty virtual base class提供特殊支持,书中的结果并未体现这种优化。
  3. Alignment的限制YZ目前有了5个字节的大小。它们的大小还会受到alignment的限制,为了它们能够更有效率地在内存中被读取。如果alignment是4个字节,还需要额外三个字节来填补,最终得到8个字节。

Empty virtual base class已经被某些编译器支持了,它提供一个virtual interface,没有定义任何数据。一个empty virtual base class被视为子类对象最开头的部分,没有花费任何任何额外空间。因此可以节省上述三种情况中的第二种所造成的一个字节,由此第三点造成的alignment也不再需要。在这种模型下,YZ均为4个字节:

Size of X: 1
Size of Y: 4
Size of Z: 4
Size of A: 8

接下来考虑A的大小。如果不考虑empty virtual base class优化,A的大小为以下几项总和:

  1. X提供了一个字节。
  2. Y的大小减去因virtual base class X而配置的大小,结果是4字节,Z同理,因此有8字节。
  3. A自己的大小为0。
  4. alignment要求。已经有了9字节,alignment到12字节。

因此A的大小为12字节。
如果考虑empty virtual base class优化,1和4的overhead将不复存在,因此A的大小为8字节。