13
#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参考?

4

2 回答 2

7

您的代码格式正确: void D::method()同时覆盖void B1::method()void B2::method()

规范声明(C++11 §10.3/2):

如果在一个类和一个类vf中声明了一个虚成员函数,直接或间接地派生自一个与被声明,然后也是虚拟的(无论它是否被声明)并且它覆盖.BaseDerivedBasevfBase::vfDerived::vfBase::vf

B1声明一个虚拟成员函数void B1::method()。类D派生自B1并且它还声明了一个具有相同名称 ( method)、相同参数列表(无参数)、相同 cv-qualification(无限定)和相同 ref-qualifier(无限定)的成员函数。

因此,void D::method()覆盖void B1::method().

同样的逻辑适用于void B2::method()(只是在上面的B2解释中替换B1),所以void D::method()覆盖了void B1::method()and void B2::method()

于 2012-07-12T20:41:42.583 回答
1

afaik 这在每个标准中都是合法的。我不确定它是否有自己的特殊名称,但它类似于钻石问题

如果您在 D 中覆盖“virtual void method()”,那么您将同时覆盖 B1 和 B2 中的方法。

编辑:

回答为什么你没有“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::method 将始终调用 B2(未重载)方法(在这种情况下不会编译,因为 B2 没有实现)

于 2012-07-12T20:07:33.207 回答