我知道在提出这个问题之前和之前我已经介绍了虚拟继承,我详细介绍了虚拟继承,并详细介绍了类似的问题,如下所示:
multiple-diamond-inheritance-compiles-without-virtual-but-doesnt-with 和 why does gcc give me an error - final overrider
我的问题略有不同,因为我没有使用纯虚函数并且明确使用虚拟继承来拥有一个唯一的'Base'类。层次结构如下:
Base
/\
/ \
Der1 Der2
\ /
Der3
我知道衍生问题上的可怕钻石,这就是我使用虚拟继承的原因。
#include <iostream>
class base
{
public :
base()
{
std::cout<<"base()" << std::endl;
}
virtual void fun()
{
std::cout<<"base" << std::endl;
}
};
class der1: virtual public base
{
public :
void fun()
{
std::cout<<"der1" << std::endl;
}
};
class der2 : virtual public base
{
public :
void fun()
{
std::cout<<"der2" << std::endl;
}
};
class der3 : public der1,public der2
{
public :
/*void fun()
{
std::cout<<"der3" << std::endl;
}*/
//if I took out the comment and the function
//is defined it compiles fine as expected
};
int main()
{
base *p=new der3;
//used scope operation explicitly to avoid ambiguity
p->base::fun(); //here it complains about 'no unique final overrider for fun'
return 0;
}
我的理解是,因为我使用虚拟继承,所以应该只有一个'base'实例,并且使用范围运算符,我可以调用虚拟有趣函数而不会产生歧义。该功能不是纯虚拟的。如果我离开并在'der3'类上实现它会给我编译器错误:
错误:'der3'中'virtual void base :: fun()'没有独特的最终覆盖
我可以看到这个问题是如何运作的(final overrider)。但我的不是。它是否在Base::fun
,der1::fun
和der2::fun
之间混淆了?范围操作员是否也有帮助?
任何线索或帮助表示赞赏。我正在使用g ++ 4.6.3。
答案 0 :(得分:11)
派生程度最高的类必须在虚拟基类中提供虚函数的实现 - 否则,在给定中间类(即der1
和{{1}的情况下,它将如何提供基类接口? })已经提供了两种选择 - 应该调用哪一种?你必须消除歧义(即使用der2
)。
当然你没有实际调用der3::fun()
,因为你明确要求der3::fun()
,但这并不意味着规则不适用,只是认为你可以实例化一个抽象类如果你不试图调用纯虚函数....程序是不正确的,直到代码绑定这些松散的结束。
答案 1 :(得分:6)
使用范围解析运算符指定您要调用base::fun
并不会使错误消失,因为即使空main()
,程序也会格式不正确。您不允许出现虚拟函数在程序中存在的任何派生类中具有多个最终覆盖的情况。
非正式地说,仅仅因为试图呼叫p->fun()
是不明确的,即使你不这样做,该程序也是不正确的。
注意:这与你重载函数的情况形成对比,在这种情况下,允许潜在的歧义 - 甚至可能是不可避免的 - 只要你避免实际会有一个调用暧昧为什么规则不同?基本上是因为即使构建der3
类型的对象也不能以合理的方式完成--- vtable指向哪个版本的fun
?