没有函数覆盖的多重继承。为什么歧义
Multiple inheritance with no function overriding. Why the ambiguity
这是我的 class。这只是
#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 未在任何地方被覆盖。我知道 class Base 有两个实例,因为没有虚拟继承。所以有两个 'var' 变量。但我不明白为什么编译器在 foo 调用中有歧义。函数不是特定于实例的。它们是 class 特定的。为什么编译器报错?
我正在使用 Visual Studio 2013.
谢谢。
多重继承让你继承函数 foo() 两次:一次作为 Derived_A
的一部分,一次作为 Derived_B
的一部分,因为每个继承它自己的 BaseClass
.
BaseClass BaseClass
| |
Derived_A Derived_A
\ /
\ /
Derived_AB
所以编译器不知道它是否应该使用 Derived_A
或 Derived_B
子对象的数据来执行它。
解决方案:
1) 您可以在每次调用时明确地消除歧义:
ABDerObj.Derived_A::foo(); // execute foo() for the Deived_A object
2) 您可以在 class 级别明确消除歧义,方法是定义一个公共 foo,例如:
void foo()
{
Derived_A::foo(); // you want all the foos called
Derived_B::foo();
}
3) 如果你只想为你的 Derived_AB
设置一个 BaseClass
,那么你应该使 BaseClass 成为 Derived_A
和 [=] 的虚拟基础 class 15=]。那么 Derived_AB
将只有一个单一的 BaseClass
并且对 foo()
的调用不再有歧义。
BaseClass
/ \
/ \
Derived_A Derived_A
\ /
\ /
Derived_AB
(P.S。在这种情况下,您还应为 Dervived_AB.
)
定义一个 BaseClass()
初始值设定项
Functions are not instance specific. They are class specific.
这仅适用于静态函数。假设我将 foo()
的实现更改为以下内容:
void foo()
{
cout << "My value is " << var << endl;
}
您希望 ABDerObj.foo();
打印什么?
既然是答案,我也提供两种可能的解决方案。
如果 foo
确实是实例特定的(例如,因为它使用了 class 字段 var
,你可以很容易地告诉编译器你想要哪个 Base::foo()
通过指定您要使用的
来调用(Derived_A
或 Derived_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& ABDerObjPartA = ABDerObj;
ABDerObjPartA.foo();
// more code using ABDerObjPartA.
另一方面,如果 - 坚持你的术语 - foo
的定义确实取决于 class 而不是实例,则将其设为 static
:
// In Base:
static void foo()
{
cout << "Class Base foo()" << endl;
}
// in main():
ABDerObj.foo(); // This is now OK
你应该真正调查的是你是否真的需要多重继承,尤其是在相同的基础上class出现不止一次。通常,一旦您开始遇到这些消歧问题,它们就会变得更糟,稍微重新设计您的代码将使其更易于维护。
这是我的 class。这只是
#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 未在任何地方被覆盖。我知道 class Base 有两个实例,因为没有虚拟继承。所以有两个 'var' 变量。但我不明白为什么编译器在 foo 调用中有歧义。函数不是特定于实例的。它们是 class 特定的。为什么编译器报错?
我正在使用 Visual Studio 2013.
谢谢。
多重继承让你继承函数 foo() 两次:一次作为 Derived_A
的一部分,一次作为 Derived_B
的一部分,因为每个继承它自己的 BaseClass
.
BaseClass BaseClass
| |
Derived_A Derived_A
\ /
\ /
Derived_AB
所以编译器不知道它是否应该使用 Derived_A
或 Derived_B
子对象的数据来执行它。
解决方案:
1) 您可以在每次调用时明确地消除歧义:
ABDerObj.Derived_A::foo(); // execute foo() for the Deived_A object
2) 您可以在 class 级别明确消除歧义,方法是定义一个公共 foo,例如:
void foo()
{
Derived_A::foo(); // you want all the foos called
Derived_B::foo();
}
3) 如果你只想为你的 Derived_AB
设置一个 BaseClass
,那么你应该使 BaseClass 成为 Derived_A
和 [=] 的虚拟基础 class 15=]。那么 Derived_AB
将只有一个单一的 BaseClass
并且对 foo()
的调用不再有歧义。
BaseClass
/ \
/ \
Derived_A Derived_A
\ /
\ /
Derived_AB
(P.S。在这种情况下,您还应为 Dervived_AB.
)
BaseClass()
初始值设定项
Functions are not instance specific. They are class specific.
这仅适用于静态函数。假设我将 foo()
的实现更改为以下内容:
void foo()
{
cout << "My value is " << var << endl;
}
您希望 ABDerObj.foo();
打印什么?
既然是答案,我也提供两种可能的解决方案。
如果 foo
确实是实例特定的(例如,因为它使用了 class 字段 var
,你可以很容易地告诉编译器你想要哪个 Base::foo()
通过指定您要使用的
Derived_A
或 Derived_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& ABDerObjPartA = ABDerObj;
ABDerObjPartA.foo();
// more code using ABDerObjPartA.
另一方面,如果 - 坚持你的术语 - foo
的定义确实取决于 class 而不是实例,则将其设为 static
:
// In Base:
static void foo()
{
cout << "Class Base foo()" << endl;
}
// in main():
ABDerObj.foo(); // This is now OK
你应该真正调查的是你是否真的需要多重继承,尤其是在相同的基础上class出现不止一次。通常,一旦您开始遇到这些消歧问题,它们就会变得更糟,稍微重新设计您的代码将使其更易于维护。