C ++中多重继承对象的内存布局

时间:2015-06-11 15:35:33

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

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

2 个答案:

答案 0 :(得分:3)

virtual中使用D1是多余的。

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

  

如果在类vf和类Base中声明虚拟成员函数Derived,直接或间接地从Base派生,则成员函数{{1与vf声明同名,参数类型列表(8.3.5),cv-qualification和ref-qualifier(或不存在相同),然后Base::vf也是虚拟的(无论是否声明)并覆盖 111 Derived::vf

           

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

因此,virtualD的内存布局(问题似乎就是这个问题)是相同的。显然,不同的类型将有不同的虚拟表。

答案 1 :(得分:1)

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

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

vtable for D:
    f1: D::f1
    f2: D::f2

vtavle for D1:
    f1: D1::f1
    f2: D1::f2