【问题标题】:virtual function table of multiple inheritance多重继承的虚函数表
【发布时间】:2014-10-20 18:59:15
【问题描述】:

示例代码如下:

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

谁能解释原因?

【问题讨论】:

  • 如果基础是无状态的,那么您实际上不需要定位基础子对象,因此您需要的派生类中的信息更少。
  • @KerrekSB 给出答案 ;)
  • @KerrekSB 你的意思是编译器对派生类进行优化以使其简单吗?
  • @KerrekSB,这似乎并不那么明显。如果我们有 C,它也从 A 继承 virtualy,而 D 从 B 和 C 继承。将 D 转换为 B 然后 A 必须具有与将 D 转换为 C 然后 A 相同的指针,即使 A 没有状态。
  • 您正在查看对象大小,而不是 v-table 大小。 sizeof(A) = v-table 指针 + k,sizeof(B) = A 的 v-table 指针 + B + k 的 v-table 指针。由于虚拟继承不再重要,因此可以在第二个 sn-p 中对其进行优化。

标签: c++ multiple-inheritance virtual-functions


【解决方案1】:

在您的子类 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 在实例数据方面为空,因此空类的虚拟继承不会增加对象的大小

【讨论】:

    【解决方案2】:

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

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

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

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

    一种流行的 C++ ABI,即 Itanium ABI,详细描述了how virtuality is implemented。还有this popular article解释了这个实现。

    【讨论】:

    • 您可以使用两个继承路径强制转换为公共基类,并且指针必须比较相等,因此必须进行调整。因此,即使没有必须在运行时确定其位置的数据,该指针也只指向 vptr。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 2010-10-11
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    相关资源
    最近更新 更多