#include <iostream>
struct B1
{
virtual void method()=0;
virtual ~B1(){}
};
struct B2
{
virtual void method()=0;
virtual ~B2(){}
};
struct D: B1, B2
{
virtual void method()
{
std::cout << "D::method\n";
};
};
int main(int argc,char *argv[])
{
D d;
B1 &b1=d;
B2 &b2=d;
b1.method();
b2.method();
return 0;
}
注意,B1和B2不共享通用接口。
这是合法的吗?如果是 - 在哪个标准? C ++ 98/03/11?
两者,msvc和gcc编译好了。
以前我认为,我必须使用一些通用接口来处理这种情况(可能的虚拟继承)。
这种情况有什么特别的名字吗?
请问详情如何?也许一些ISO参考?
答案 0 :(得分:7)
您的代码格式正确:void D::method()
会覆盖void B1::method()
和void B2::method()
。
规范陈述(C ++11§10.3/ 2):
如果在类
vf
和类Base
中声明虚拟成员函数Derived
,直接或间接地从Base
派生,则成员函数{{1声明同名,参数类型列表,cv-qualification和ref-qualifier(或缺少相同),vf
也是虚拟的(无论是否为如此声明)并覆盖Base::vf
。
Derived::vf
声明虚拟成员函数Base::vf
。类B1
派生自void B1::method()
,它还声明了一个具有相同名称(D
),相同参数列表(无参数),相同cv资格(无资格)的成员函数)和相同的参考资格(没有资格)。
因此,B1
会覆盖method
。
同样的逻辑适用于void D::method()
(在上述说明中仅用void B1::method()
代替void B2::method()
),因此B2
会覆盖B1
和{{1} }}
答案 1 :(得分:1)
afaik这在每个标准中都是合法的。我不确定它是否有自己的特殊名称,但它与diamond problem类似。
如果在D中覆盖“virtual void method()”,则覆盖B1和B2中的方法。
修改强>
向anwser说明为什么你没有“D:B1 :: method和B2 :: method”中的“两个不同的独立继承虚函数”:
当覆盖方法时,您只能指定函数名称,返回类型和参数,但是无法在覆盖时添加有关从哪一个继承的签名详细信息。
想象一下它是可能的,那么它看起来像这样:
struct D: B1, B2
{
virtual void B1::method()
{
std::cout << "D::method\n";
};
virtual void B2::method()
{
std::cout << "D::method\n";
};
};
但看到这一点,你已经可以说没有可能有这样的东西了,因为在打电话时
objectD.method()
您无法指定要呼叫的是哪一个。因此,即使有两种方法都要超载,仍然存在区分函数调用的问题。
修改强> “无法指定你打电话给哪一个。”指的是,你不能指定是否要调用B2 :: method的D类重载或B2方法本身。 objectD.B2 ::方法将始终调用B2(不重载)方法(在这种情况下不会编译,因为B2没有实现)