简体   繁体   English

无功能覆盖的多重继承。 为什么模棱两可

[英]Multiple inheritance with no function overriding. Why the ambiguity

Here are my classes. 这是我的课。 This is just 这只是

#include<iostream>
using namespace std;

class Base
{
public:
    int var;

    Base(int val) : var(val)
    {}

    void foo()
    {
        cout << "Class Base foo()" << endl;
    }
};

class Derived_A : public Base
{
public:
    Derived_A(int val) : Base(val)
    {}
};

class Derived_B : public Base
{
public:
    Derived_B(int val) : Base(val)
    {}
};

class Derived_AB : public Derived_A, public Derived_B
{
public:
    Derived_AB(int var1, int var2) : Derived_A(var1), Derived_B(var2)
    {}
};

int main(int argc, char** argv)
{
    Derived_AB ABDerObj(1,2);
    ABDerObj.foo();
    return 0;
}

And this gives me a compiler error saying the foo call is ambiguous. 这给了我一个编译器错误,说foo调用是模棱两可的。

Function foo is not overridden anywhere. 函数foo在任何地方都不会被覆盖。 I understand there are two instances of class Base because there is no virtual inheritance. 我了解有Base类的两个实例,因为没有虚拟继承。 So there are two 'var' variables. 因此,有两个“ var”变量。 But I don't understand why the compiler is having ambiguity in foo call. 但是我不明白为什么编译器在foo调用中有歧义。 Functions are not instance specific. 函数不是特定于实例的。 They are class specific. 它们是特定于类的。 Why is the compiler giving an error? 为什么编译器给出错误?

I am using Visual Studio 2013. 我正在使用Visual Studio 2013。

Thank you. 谢谢。

The multiple inheritance makes you inherit two times the function foo(): one as part of Derived_A and one as part of Derived_B , because each of it inherits its own BaseClass . 多重继承使您可以继承函数foo()的Derived_A :一次是Derived_A一部分,一次是Derived_B一部分,因为每个继承自自己的BaseClass

BaseClass      BaseClass
    |               |
Derived_A      Derived_A  
     \           /
      \         /
       Derived_AB

So the compiler doesn't know if it shall execute it with the data of the Derived_A or Derived_B subobject. 因此,编译器不知道是否应使用Derived_ADerived_B子对象的数据执行它。

Solutions: 解决方案:

1) You can disambiguate explicitely in every call you make: 1)您可以在每次通话中明确消除歧义:

ABDerObj.Derived_A::foo();  // execute foo() for the Deived_A object

2) You can disambiguate explicitely at the class level, by defining a common foo, for example: 2)您可以通过定义公共foo在类级别上明确消除歧义,例如:

void foo()
{
    Derived_A::foo();   // you want all the foos called
    Derived_B::foo();
}

3) If you want to have only a single BaseClass for your Derived_AB , then you should make BaseClass a virtual base class for Derived_A and Derived_B . 3)如果您只希望Derived_AB具有单个BaseClass ,则应使BaseClass成为Derived_ADerived_B的虚拟基类。 Then Derived_AB will have only one single BaseClass and the call to foo() is no longer ambiguous. 然后Derived_AB将只有一个BaseClass并且对foo()的调用不再是模棱两可的。

        BaseClass
       /        \
      /          \
Derived_A      Derived_A  
     \           /
      \         /
       Derived_AB  

(PS in this case, you shall also define a BaseClass() initializer for Dervived_AB. ) (在这种情况下,PS还将为Dervived_AB.定义一个BaseClass()初始化Dervived_AB.

Functions are not instance specific. 函数不是特定于实例的。 They are class specific. 它们是特定于类的。

That is only true for static functions. 这仅适用于静态函数。 Suppose I change your implementation of foo() to the following: 假设我将foo()实现更改为以下内容:

void foo()
{
    cout << "My value is " << var << endl;
}

What do you expect ABDerObj.foo(); 您期望ABDerObj.foo(); to print? 打印?


Since this is an answer, let me also provide two possible solutions. 因为这是一个答案,所以让我也提供两种可能的解决方案。

If foo really is instance-specific (for example, because it uses the class field var , you can easily tell the compiler which Base::foo() you want to call (the Derived_A or the Derived_B version) by specifying which one you want to use 如果foo确实是特定于实例的(例如,因为它使用类字段var ,则可以通过指定所需的哪个)来轻松告诉编译器您要调用哪个Base::foo()Derived_ADerived_B版本)使用

ABDerObj.Derived_A.foo();      // prints: My value is 1
ABDerObj.Derived_B.foo();      // prints: My value is 2

or by just throwing away the other part: 或只丢掉另一部分:

((Derived_A) ABDerObj).foo();  // prints: My value is 1
((Derived_B) ABDerObj).foo();  // prints: My value is 2

The latter is mostly useful if you have a block of code where you are going to use only the Derived_A functionality, for example: 如果您有一个代码块使用Derived_A功能,则Derived_A有用,例如:

Derived_A& ABDerObjPartA = ABDerObj;
ABDerObjPartA.foo();
// more code using ABDerObjPartA.

On the other hand, if -- to stick with your terminology -- the definition of foo really depends on the class and not on the instance, make it static : 在另一方面,如果-坚持使用您的术语-的定义foo真的取决于类,而不是实例,使之static

// In Base:
static void foo()
{
    cout << "Class Base foo()" << endl;
}

// in main():
ABDerObj.foo(); // This is now OK

What you should really be looking into is whether you actually need multiple inheritance, especially with the same base class occurring more than once. 真正应该研究的是您是否确实需要多重继承,尤其是同一基类多次出现。 Often once you start having these disambiguation problems they keep getting worse and a slight redesign of your code will make it much more maintainable. 通常,一旦开始出现这些歧义性问题,它们就会变得越来越糟,对代码进行稍微的重新设计将使其更加易于维护。

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

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