我正在学习多重继承和钻石问题,当我从最派生的类中调用函数时,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类中重写了基类函数,那么调用将是不明确的,但不是&#34; aFunction()&#34;在B和C中是一样的吗?
此外,使B和C从A继承实际上会使错误消失。但我对关键字&#34;虚拟&#34;的理解当继承,即(Derived:virtual Base)时,它会阻止一个更多的派生类&#34;从链上继承Base的多个副本进一步向下。在继承中,可以继承成员变量的多个副本,但只能复制具有相同名称的函数的一个副本。因此,例如,我可以有5个派生类,每个派生自Base,然后是从所有5个派生类继承的MostDerivedClass,在MostDerivedClass中,我将拥有5个Base类和#34;成员变量&#34;的副本,但仅限于一个具有相同名称的函数的副本。
换句话说,&#34;虚拟&#34;继承关键字应该防止多个Base&#34;成员变量&#34;副本。我不明白为什么在这种情况下它会清除一个模糊的函数调用。
编辑:谢谢你,它正在慢慢沉入。我无法想象&#34;两份副本&#34; D中的A,因为A是空的(没有大小)。但后来我记得C ++从不创建空类,在我的设置上,例如一个空类的大小为1.然后我能够想象&#34;两个副本&#34; D中的A,它现在开始有意义了。答案 0 :(得分:5)
调用不明确,因为有两个可能的private string ReturnTop(IEnumerable<string> current, IEnumerable<string> topList)
{
var topMap = topList.Select((value, index) => new {Value = value, Index = index})
.ToDictionary(item => item.Value, item => item.Index);
string minItem = null;
int minPosition = topMap.Count;
foreach (var item in current)
{
var currentPosition = topMap[item];
if (currentPosition == 0)
{
return item;
}
if (currentPosition < minPosition)
{
minPosition = currentPosition;
minItem = item;
}
}
return minItem;
}
基础对象可以作为调用的A
参数传递。即使它是最终被调用的相同的物理函数,并且该函数完全忽略了它的this
参数,但是它们中有两个使它变得模棱两可。
使用this
继承意味着只有一个virtual
基础对象,因此调用不会有歧义。
答案 1 :(得分:2)
由于成员变量的多个副本是继承的,因此您可以拥有两个具有不同行为的函数的单独副本。
struct A
{
int x;
virtual void aFunction() { cout << "I am A with value " << x ; }
};
struct B : A {
};
struct C : A {
};
struct D : B, C {};
int main()
{
D DObj;
((B*)(&DObj))->x = 0; // set the x in B to 0
((C*)(&DObj))->x = 1; // set the x in C to 1
DObj.aFunction(); // This is an ambiguous call
}
这个输出应该是0还是1?
编译器可以检测到没有引用它的内联函数的特定情况,但是您可以轻松地解决该问题,因此对于相对罕见的情况而言,它不值得复杂。
答案 2 :(得分:0)
使用虚拟继承来解决钻石问题:
struct A
{
int x;
virtual void aFunction() { cout << "I am A with value " << x ; }
};
struct B : virtual A { // add virtual
};
struct C : virtual A { // virtual
};
struct D : B, C {};