C++ 没有函数重写的多重继承。为什么会有歧义

C++ 没有函数重写的多重继承。为什么会有歧义,c++,multiple-inheritance,C++,Multiple Inheritance,这是我的课。这只是 #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 { pu

这是我的课。这只是

#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;
}
#包括
使用名称空间std;
阶级基础
{
公众:
int-var;
基本值(int val):变量(val)
{}
void foo()
{

cout多重继承使您继承两次函数foo():一次作为
派生的\u A
的一部分,另一次作为
派生的\u B
的一部分,因为每个继承都继承自己的
基类

BaseClass      BaseClass
    |               |
Derived_A      Derived_A  
     \           /
      \         /
       Derived_AB
因此,编译器不知道是否应该使用
派生的_A
派生的_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) 如果您想为您的
派生的\u AB
只拥有一个
基类
,那么您应该使基类成为
派生的\u a
派生的\u B
的虚拟基类。然后
派生的\u AB
将只有一个
基类
,对
foo()
的调用不再含糊不清

        BaseClass
       /        \
      /          \
Derived_A      Derived_A  
     \           /
      \         /
       Derived_AB  
(注意:在这种情况下,您还应为
Dervived_AB.
定义一个
BaseClass()
初始值设定项。)


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

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

void foo()
{
    cout << "My value is " << var << endl;
}
或者扔掉另一部分:

((Derived_A) ABDerObj).foo();  // prints: My value is 1
((Derived_B) ABDerObj).foo();  // prints: My value is 2
如果您有一个只使用
派生功能的代码块,则后者最有用,例如:

Derived_A& ABDerObjPartA = ABDerObj;
ABDerObjPartA.foo();
// more code using ABDerObjPartA.
另一方面,如果——坚持你的术语——
foo
的定义确实取决于类而不是实例,那么就让它成为
静态的

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

// in main():
ABDerObj.foo(); // This is now OK
//在Base中:
静态void foo()
{

难道这就是当前标准中的
virtual
继承的目的。“函数不是特定于实例的”-你错了,它们是。谢谢你。我的理解是,编译器将每个非静态成员类作为参数传递一个“*this”,这就是为什么你可以这样做“我的理解是,一个类的每个成员函数只存在一个函数的副本。编译器隐式地将“*this”传递给每个成员函数,这就是为什么成员函数可以访问实例特定的成员。这不是为什么可以简单地执行(POD)的memcopy的原因吗?”对象来创建一个新对象?@madu的确,非静态成员函数有一个隐式的
这个
参数。没有“复制”这样的东西函数的。函数不是对象。成员函数不是数据成员,也不存在于对象实例中。
memcpy
处理POD对象的原始内存,即类的数据成员。可以打印某些对象表示的单个字节,但不能打印函数。指向函数的指针不是指向对象的指针。您不能将指向函数的指针转换为
char*
,并使用结果。@madu从技术上讲,您的函数只存在一个代码。但是,当编译器生成对成员函数的调用时,他会向它提供指向基类对象的“this”指针。在您的示例中,除非您将其设置为虚拟的继承,有两个不同的子对象。@Christophe好的。我现在知道了。foo只有一个实现,但要传递两个不同的“*this”,因为有两个基类实例。谢谢。这就是我所困惑的。
// In Base:
static void foo()
{
    cout << "Class Base foo()" << endl;
}

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