【问题标题】:memory layout of a multiple-inherited object in C++C++中多重继承对象的内存布局
【发布时间】:2015-08-27 09:53:39
【问题描述】:
class B1 {
    virtual void f1();
    int int_in_b1;
};
class B2 {
    virtual void f2();
    int int_in_b2;
};
class D: B1, B2 {
    int int_in_d;
    void f1();
    void f2();
};
class D1: B1, B2 {
    int int_in_d;
    virtual void f1();
    virtual void f2();
};

基于这个article,类D的对象d的内存布局是这样的:

d:
  +0: pointer to virtual method table of D (for B1)
  +4: value of int_in_b1
  +8: pointer to virtual method table of D (for B2)
 +12: value of int_in_b2
 +16: value of int_in_d

virtual method table of D (for B1):
  +0: D::f1()  // B1::f1() is overridden by D::f1()

virtual method table of D (for B2):
  +0: D::f2()   // B2::f2() is overridden by D::f2()

D1 类的对象呢?在D1 类中,成员f1f2 都声明为virtual

【问题讨论】:

  • 动态多态的实现是一个实现细节,而不是C++本身的事实。因此,请指定您正在谈论的 ABI。
  • @jxh,错别字。应该是B1和B2
  • 为什么 B1::f1() 在 D 中没有被覆盖?
  • @newbie:来自维基百科文章的剪切和粘贴错误,它说明了如果您不覆盖会发生什么。我解决了这个问题。

标签: c++ compiler-construction multiple-inheritance


【解决方案1】:

virtual 的使用在 D1 中是多余的。

来自 C++11,§10.3¶2:

如果在类Base和类Derived中声明一个虚成员函数vf,直接或间接派生自Base,则成员函数vf具有相同的名称,参数类型-list (8.3.5)、cv-qualification 和 ref-qualifier(或不存在相同的)作为 Base::vf 被声明,那么 Derived::vf 也是虚拟的(无论是否如此声明) 并覆盖111Base::vf


111) 作为虚函数具有相同名称但参数列表不同的函数(第 13 条)不一定是虚函数,并且不会覆盖。在覆盖函数的声明中使用 virtual 说明符是合法的,但是是多余的(具有空语义)。在确定覆盖时不考虑访问控制(第 11 条)。

因此,DD1 的内存布局(这似乎是问题所在)是相同的。显然,不同的类型会有不同的虚拟表。

【讨论】:

    【解决方案2】:

    f1()f2()D 中也是虚拟。如果一个函数被声明为virtual,它在任何继承的类中仍然是virtual

    因此,DD1 类在内部几乎没有区别(但显然,它们是不同的类型),但它们都提供了 f1f2 的实现,以及它们的 虚拟表 会有所不同,因为D 的虚拟表将指向D 的实现,D1 也是如此。

    vtable for D:
        f1: D::f1
        f2: D::f2
    
    vtavle for D1:
        f1: D1::f1
        f2: D1::f2
    

    【讨论】:

    • 但是虚拟方法表的内容肯定会有所不同……
    • @JonasWielicki,这正是我想问的。虚方法表有什么区别?
    • 根据您的更新,它们似乎是相同的。
    • @Daniel 每个DD1 都为f1f2 提供自己的实现。虚拟表将分别指向 DD1 的实现。
    • @FihopZz 不,他们不是。
    猜你喜欢
    • 2012-07-09
    • 2015-09-01
    • 2012-06-18
    • 2023-03-13
    • 1970-01-01
    • 2011-06-04
    • 2020-09-30
    • 2012-07-21
    相关资源
    最近更新 更多