虚方法对多重继承的行为有所不同

时间:2013-05-09 00:32:32

标签: c++ inheritance multiple-inheritance name-lookup class-members

为什么会起作用

struct Base {
    virtual void visit(const A &) { };
    virtual void visit(const B &) { };
}

这会在调用访问方法

时抱怨模棱两可
template< typename T >
struct X {
    virtual void visit(const T &) { };
};

struct Base: X< A >, X< B > { };

这也显示了同样的问题:

struct Y {
   virtual void visit(const A &) { };
};

struct Z {
    virtual void visit(const B &) { };
};

struct Base: Z, Y { };

不知怎的,它看起来像多重继承混淆了虚函数签名...

使用gcc版本4.8.0 20130411(预发布)

1 个答案:

答案 0 :(得分:0)

这里virtual-ness是无关紧要的,2个基类是模板类的事实是无关紧要的。具有相同问题的更简单的代码是:

struct A {
   void f(const A &) { }
};

struct B {
    void f(const B &) { }
};

struct Der: A,B { };

此处Der有两个继承的成员:A::f(const A &)B::f(const B &);它们可以这样调用:

Der d;
d.A::f(d);
d.B::f(d);

这样:

d.f((A&)d); // error: ambiguous name lookup
d.f((B&)d); // error: ambiguous name lookup

成员函数重载分辨率以您的思维方式工作(找到f然后保留具有兼容参数列表的那个。)

在C ++中,成员名称查找查找具有给定名称的所有非隐藏成员声明,​​因此它在此处找到A::f(const A &)B::f(const B &),如果它立即失败,这些成员不会在同一个类中声明。

您可以通过在同一个类中添加2个声明来解决此问题:

struct Der: A,B {
    using A::f; // imports A::f(const A &)
    using B::f; // imports B::f(const B &)
};

然后你可以这样做:

Der d;
d.f((A&)d); // OK: Der::f(&A)

请记住:这纯粹是成员名称查找歧义。