多重继承的虚拟函数表

virtual function table of multiple inheritance

本文关键字:函数 虚拟 多重继承      更新时间:2023-10-16

示例代码如下:

class A
{
public:
    int k;
    virtual int f();
};
class B:public virtual  A
{
public:
    virtual int a();
};
int main()
{
    cout<<sizeof(A)<<sizeof(B);
}

它打印

8 12

class B似乎有了自己新的虚拟函数表。

如果class A更改为:

class A
{
public:
    virtual int f();
};

它打印

4 4

有人能解释一下原因吗?

在子类B中,B是a的虚拟子类。因此,B在子对象a上有一个单独的vtbl指针(4字节)。因此,

sizeof(B object) 
= sizeof(A object) + sizeof (vtbl pointer of B)
= sizeof(int) + sizeof (vtbl pointer of A) + sizeof (vtbl pointer of B)
= 4 + 4 + 4
= 12

而且,

sizeof(A object)
= sizeof(int) + sizeof (vtbl pointer of A)
= 4 + 4
= 8

如果B是a的正常子类,

 sizeof(B object) 
    = sizeof(A object) 
    = sizeof(int) + sizeof (vtbl pointer of A) 
    = 4 + 4
    = 12

对于空类A,为sizeof A对象分配的最小大小是vtbl=4的sizeof指针由于A在实例数据方面是空的,所以空类的虚拟继承不会增加对象的大小

在类继承的上下文中,"虚拟"的意思是"在运行时确定"。有两个独立的东西可以是虚拟的,并且实现必须以某种方式实现:

  • 虚拟函数,必须在运行时确定要调用的实际函数:x.f()谁是f?常见的实现涉及函数指针表。

  • 虚拟继承,其中虚拟基础子对象直到运行时才知道。实现必须提供一种定位实际基础对象的机制:x.a = 10其中a?这方面的常见实现涉及指针偏移量计算。

如果一个虚拟基类没有状态(这与"为空"类似,但不等价),那么第二个用例就变成了空的。由于不存在位置必须动态确定的数据成员,因此实现不需要为此生成任何信息,对象也不需要存储相关引用。

一个流行的C++ABI,安腾ABI,详细描述了虚拟性是如何实现的。还有一篇很受欢迎的文章解释了这个实现。