为什么会起作用
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(预发布)
答案 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)
请记住:这纯粹是成员名称查找歧义。