【发布时间】:2017-05-15 16:57:54
【问题描述】:
我正在学习多重继承和菱形问题,当我从最派生的类中调用函数时,Visual Studio 告诉我调用不明确:
struct A
{
virtual void aFunction() { cout << "I am A\n"; }
};
struct B : A {};
struct C : A {};
struct D : B, C {};
int main()
{
D DObj;
DObj.aFunction(); // This is an ambiguous call
}
我知道如果我在 B 和 C 类中重写了基类函数,那么调用将是不明确的,但 B 和 C 中的“aFunction()”不一样吗?
此外,使 B 和 C 从 A 继承实际上会使错误消失。但是我对继承时的关键字“virtual”的理解,即(Derived:virtual Base),它可以防止更下游的“更多派生类”继承链上Base的多个副本。在继承中,可以继承多个成员变量副本,但只能继承同名函数的一个副本。因此,例如,我可以有 5 个派生类,每个派生自 Base,然后是从所有 5 个派生类继承的 MostDerivedClass,在 MostDerivedClass 中,我将拥有 Base 类“成员变量”的 5 个副本,但只有一个函数的副本同名。
换句话说,继承的“virtual”关键字应该防止多个Base“成员变量”副本。我不明白为什么在这种情况下它会清除一个模棱两可的函数调用。
编辑:谢谢,它正在慢慢下沉。我无法想象 D 中 A 的“两个副本”,因为 A 是空的(没有大小)。但后来我记得 C++ 从不创建空类,例如在我的设置中,一个空类的大小为 1。然后我能够想象 A 在 D 中的“两个副本”,现在它开始变得有意义了。
【问题讨论】:
-
我认为没有虚拟你有两个相同的功能副本(尽管这仍然是我必须自己研究的东西)
-
是的,没错。 D 包含 A 的两个实例。编译器不知道您是要调用 D::B::A::aFunction 还是 D::C::A::aFunction。尽管在任何一种情况下调用的函数都是相同的,但不同的调用会得到不同的
this指针。如果您从 A 虚拟派生,那么您将只有一个 A 并且没有歧义。struct B : virtual A {};和struct C : virtual A {};. -
而且(只是为了证明这不是 Visual C++ 编译器的问题),GCC 5.1 给出了the same error
-
这个函数调用真的模棱两可吗? -- 如果世界各地成千上万使用的编译器在使用您的示例代码时遇到如此简单的错误,您就会知道关于它,相信我。
-
你上面有所谓的可怕的钻石 Here is a good tidbit。
标签: c++ inheritance polymorphism virtual