繁体   English   中英

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

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

这是我的课。 这只是

#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;
}

这给了我一个编译器错误,说foo调用是模棱两可的。

函数foo在任何地方都不会被覆盖。 我了解有Base类的两个实例,因为没有虚拟继承。 因此,有两个“ var”变量。 但是我不明白为什么编译器在foo调用中有歧义。 函数不是特定于实例的。 它们是特定于类的。 为什么编译器给出错误?

我正在使用Visual Studio 2013。

谢谢。

多重继承使您可以继承函数foo()的Derived_A :一次是Derived_A一部分,一次是Derived_B一部分,因为每个继承自自己的BaseClass

BaseClass      BaseClass
    |               |
Derived_A      Derived_A  
     \           /
      \         /
       Derived_AB

因此,编译器不知道是否应使用Derived_ADerived_B子对象的数据执行它。

解决方案:

1)您可以在每次通话中明确消除歧义:

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

2)您可以通过定义公共foo在类级别上明确消除歧义,例如:

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

3)如果您只希望Derived_AB具有单个BaseClass ,则应使BaseClass成为Derived_ADerived_B的虚拟基类。 然后Derived_AB将只有一个BaseClass并且对foo()的调用不再是模棱两可的。

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

(在这种情况下,PS还将为Dervived_AB.定义一个BaseClass()初始化Dervived_AB.

函数不是特定于实例的。 它们是特定于类的。

这仅适用于静态函数。 假设我将foo()实现更改为以下内容:

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

您期望ABDerObj.foo(); 打印?


因为这是一个答案,所以让我也提供两种可能的解决方案。

如果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

或只丢掉另一部分:

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

如果您有一个代码块使用Derived_A功能,则Derived_A有用,例如:

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

在另一方面,如果-坚持使用您的术语-的定义foo真的取决于类,而不是实例,使之static

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

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

真正应该研究的是您是否确实需要多重继承,尤其是同一基类多次出现。 通常,一旦开始出现这些歧义性问题,它们就会变得越来越糟,对代码进行稍微的重新设计将使其更加易于维护。

暂无
暂无

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

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