【问题标题】:virtual method behaves differently with multiple inheritance虚拟方法的行为与多重继承不同
【发布时间】:2013-05-03 09:05:08
【问题描述】:

为什么会这样

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(预发布)

【问题讨论】:

  • 旁注:在 } 结束函数体之后,您不需要 ;,就像在 virtual void visit(const A &amp;) { }; 中那样,这很难看。

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


【解决方案1】:

这里的虚拟性是无关紧要的,并且 2 个基类是模板类这一事实是无关紧要的。具有相同问题的更简单的代码是:

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

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

struct Der: A,B { };

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

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++ 中,member name-lookup 查找具有给定名称的所有非隐藏成员声明,​​因此在此处找到 A::f(const A &amp;)B::f(const B &amp;),如果这些成员不存在则立即失败在同一个类中声明。

你可以通过在同一个类中添加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)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 2017-03-31
    • 2015-11-21
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 2013-11-19
    相关资源
    最近更新 更多