25

看下面的 C++ 代码

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和Derived类的虚表布局是这样的: 在此处输入图像描述

在此处输入图像描述

我的问题是:

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

4

2 回答 2

6

好吧,首先,我要提醒大家,实现多态性的解决方案的设计是标准之外的 ABI 决策。例如,MSVC 和 Itanium ABI(其次是 gcc、clang、icc 等)有不同的实现方式。

顺便说一句,我认为这是对查找的优化。

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

于 2013-04-10T09:06:14.860 回答
-2

在运行时当你得到:

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

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

于 2016-03-13T13:40:47.777 回答