虚拟表正是为Diamond继承中的哪个类创建的

Virtual table is exactly created for which class in Diamond Inheritance?

本文关键字:创建 继承 Diamond 虚拟      更新时间:2023-10-16

考虑以下代码片段:

class A
{
};
class B:public virtual A
{
};
class C:public virtual A
{
};
class D:public B,public C
{
};
int main()
{
    cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C)<<" "<<sizeof(D));
    return 0;
}

我得到的输出为:

1 4 4 8

由于vptr的创建,类BC的大小是4个字节。这是否意味着virtual table是为类BC创建的?A呢?

通常,编译器会为哪些类创建菱形继承中的virtual table
创建虚拟表的决定是编译器特定的吗

请在上面的例子或任何其他更好的例子的背景下回答。

是的,具有虚拟基的类需要某种类型的vtable或等价物。您需要一些机制来在运行时查找实际的基子对象!(请记住,虚拟基本子对象是最派生的对象的责任,而不是直接继承的对象的责任。)

如果编译器生成VTABLES,他将为任何需要VTABLES的类(包含虚拟函数…)生成

A不需要VTABLE=>size==1[最小尺寸]

B需要一个=>大小==4[您使用的是32位…]

C也需要一个=>大小==4

D也需要一个=>大小==8(2个条目,每个VTABLE D引用一个)

将为B、C和D创建虚拟表。B和C各有一个VPTR,D有两个VPTR。一个指向VTable的B部分,另一个指向VT的C部分。

注意:VTable不是强制性的,只要继承关系能够正确建模,编译器就可以提供自己的实现。(但是大多数编译器实现VTables)

没有任何内容表明编译器为任何类创建vptr。也就是说,在现实生活中,编译器生成vptrs的原因有两个:

  1. 虚拟调度(显而易见)
  2. RTTI,例如dynamic_cast要求的RTTI(不那么明显)

通常,类的vtable中的一个条目将指向某种"类型信息"结构,该结构为RTTI的工作提供了足够的信息。

正是这些信息使编译器能够计算出如果将B*C*D*中的任何一个强制转换为A*该怎么办,因此对于BC,需要vptr。CCD_ 20简单地聚合了两者。