关于oop:MI的C ++虚拟表布局(多重继承)

C++ virtual table layout of MI(multiple inheritance)

看看下面的C++代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Base1 {  
public:  
    Base1();  
    virtual ~Base1();  
    virtual void speakClearly();  
    virtual Base1 *clone() const;  
protected:  
    float data_Base1;  
};  

class Base2 {  
public:  
    Base2();  
    virtual ~Base2();  
    virtual void mumble();  
    virtual Base2 *clone() const;  
protected:  
    float data_Base2;  
};  

class Derived : public Base1, public Base2 {  
public:  
    Derived();  
    virtual ~Derived();  
    virtual Derived *clone() const;  
protected:  
    float data_Derived;  
};

"C++对象模型内部"4.2表示类Base1、Base2和派生类的虚拟表布局如下:enter image description here

氧化镁

我的问题是:

派生类的base1子对象的虚拟表包含Base2::mumble,为什么?我知道派生类与base1共享了这个虚拟表,所以我认为base2的函数不应该出现在这里。有人能告诉我为什么吗?谢谢。


首先,我要提醒大家,实现多态性的解决方案的设计是一个超出标准的ABI决策。例如,MSVC和ItaniumABI(后面跟着GCC、Clang、ICC等)有不同的实现方法。

如果不这样做,我认为这是一个查找优化。

当您有一个Derived对象(或其后代之一)并查找mumble成员时,您不需要实际查找Base2子对象,而是可以直接从Base1子对象(其地址与Derived子对象一致,因此不涉及算术)。


在运行时,当您得到:

1
2
3
    Base2 b2;
    Base1* b1_ptr = (Base1*)&b2;
    b1_ptr->mumble();    // will call Base2::mumble(), this is the reason.

然后需要调用base2::mumble()!注意,mumble()是层次结构中唯一被重写的虚拟方法。(甚至,您可能认为clone()也被重写,但它在类之间返回不同的类型,那么它是另一个签名)。