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

memory layout of a multiple-inherited object in C++

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,classD的一个对象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()

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

f1()f2()D 中也是 virtual。如果函数被声明为 virtual,它在继承的任何 class 中保持 virtual

所以,class是DD1内部几乎没有区别(但是,很明显,是不同的类型),但是它们都给出了[=16=的实现] 和 f2,它们的 虚拟 tables 将不同,因为 D 的虚拟 table 将指向 D 的实现,D1.

也是如此
vtable for D:
    f1: D::f1
    f2: D::f2

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

virtualD1 中的使用是多余的。

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

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides111 Base::vf.


111) A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtual and does not override. The use of the virtual specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (Clause 11) is not considered in determining overriding.

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