简体   繁体   English

虚拟和非虚拟继承的混合

[英]mixture of virtual and non-virtual inheritance

while trying to analyse in greater depth inheritance mechanism of C++ I stumbled upon the following example: 在尝试更深入地分析C ++的继承机制时,我偶然发现了以下示例:

#include<iostream>

using namespace std;

class Base {
public:
    virtual void f(){
    cout << "Base.f" << endl; 
    }
};

class Left : public Base { //NOT VIRTUAL!!!
public:
void g(){ 
        f();
    }     
};

class Right : public Base{
public:
    virtual void f(){
    cout << "Right.f" << endl; 
    }
};

class Bottom : public Left, public Right{
public:
    Bottom(int arg){ }
    //void f() { }
};

int main(int argc,char **argv)
{
    Bottom* b = new Bottom(23);
    b->g();
}

It is clear that calling 很明显,打电话

b->f()

is ambiguous, so there is no unique method f() on object Bottom. 是不明确的,所以对象底部没有唯一的方法f() Now, calling 现在,打电话

b->g()

works fine and prints 工作正常和打印

Base.f

Well, as far as I see this: 好吧,据我所知:

  1. static type is Bottom, so we call its g() method, as it is non-virtual static类型是Bottom,所以我们称之为g()方法,因为它是非虚拟的
  2. g() method is inherited from Left, so we call this inherited method g()方法是从Left继承的,所以我们称之为继承方法
  3. Now, g() in Left tries to call virtual method f() . 现在,左边的g()尝试调用虚方法f() According to C++ sepcification, we call f() method of a dynamic type of our pointer (which is Bottom) 根据C ++ sepcification,我们调用f()方法的动态类型的指针(这是底部)

BUT Bottom does not have method f() ... at least not a unique one. 但是底部没有方法f() ......至少不是唯一的方法。 Why does this program executes Left::Base::f() rather than Right::Base::f() or why does it simply not states that call to f() is ambiguous from Bottom? 为什么这个程序执行Left::Base::f()而不是Right::Base::f()或者为什么它只是没有声明调用f()从Bottom是不明确的?

The short answer is that (as you noted), Bottom does not have method f() , so there is no need in trying to call it. 简短的回答是(如你所说), Bottom没有方法f() ,因此没有必要尝试调用它。

Bottom contains the two subobjects Left and Right . Bottom包含两个子对象LeftRight Each of them inherits from Base , so Bottom contains the member functions Left::f() and Right::f() , but no Bottom::f() . 它们中的每一个都继承自Base ,因此Bottom包含成员函数Left::f()Right::f() ,但没有Bottom::f() Since Bottom does not override Left::f() (using Right::f() for example), Base::f() is the unique final overrider in Left::g() . 由于Bottom不会覆盖Left::f() (例如使用Right::f() ),因此Base::f()Left::g()唯一的最终覆盖。

cf. 比照 the example in 10.3.9 from the C++03 standard. 来自C ++ 03标准的10.3.9中的示例。

Since there is no virtual inheritance there are two copies of the Base object in your Bottom object. 由于没有虚拟继承,因此Bottom对象中有两个Base对象副本。 But if you move up the hierarchy to Left where g() is defined, there is a single Base subobject and that is the one being called. 但是,如果将层次结构向上移动到Left ,其中定义了g() ,则会有一个Base子对象,即被调用的子对象。 Since it is not overridden in Left (or Bottom ) it will call the Base version. 由于它不会在Left (或Bottom )中被覆盖,因此它将调用Base版本。 Note that Right::f() only overrides f() for it's own Base subobject. 注意, Right::f()只覆盖它自己的Base子对象的f()

Calling f directly on Bottom is ambiguous, as there is no f() in Bottom it will try to look in it's bases and will find Left::Base::f and Right::Base::f and the compiler does not know which of the two to use. 直接在Bottom上调用f是不明确的,因为在Bottom没有f()它会尝试查看它的基础并找到Left::Base::fRight::Base::f并且编译器不知道哪个两个使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM