class messageA {
};
class messageB {
};
template<class T>
class queue {
public:
virtual ~queue() {}
void submit(T& x) {}
};
class A : public queue<messageA>, public queue<messageB>
{
};
int main()
{
A aa;
aa.submit(messageA());
aa.submit(messageB());
}
我的第一个想法是,上面的代码应该没问题,因为A类将包含2个重载的提交函数,它们将接受messageA和messageB对象。
但是,编译器给出了以下错误:
我可以知道为什么会有歧义吗?是不是很明显,对于第一次提交电话,我想打电话给messageA版本?对于第二次提交呼叫,我想呼叫messageB版本?
------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
could be the 'submit' in base 'queue<messageA>'
or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
could be the 'submit' in base 'queue<messageA>'
or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
with
[
T=messageA
]
.\main.cpp(22) : error C3861: 'submit': identifier not found
答案 0 :(得分:11)
我现在没有编译器,但我猜一个继承可以隐藏另一个:编译器将使用Koenig Lookup来找到正确的符号,如果我没记错的话,一旦编译器找到合适的符号(即,一种称为“提交”的方法,它将停止在父和/或外部范围内搜索其他人。
在这种情况下,我认为继承类都将被搜索符号,但没有你的确切编译器(Visual C ++ 2003?2008?2010?),我无法猜到更多。
经过一些思考,另一种可能性是编译器确实找到了两个符号,但是无法决定调用哪个(在符号解析的那一刻,编译器只关心符号名称,而不是它的确切原型)。我相信这最后的解释是正确的。
尝试在派生类中添加using语句:
class A : public queue<messageA>, public queue<messageB>
{
using queue<messageA>::submit ;
using queue<messageB>::submit ;
} ;
将两个提交方法直接放在A类范围内。
另请注意,您的提交方法将消息作为非const引用,而在构造函数中,您的消息参数是临时值(因此,const r值)。
将主要重写为:
int main()
{
A aa;
messageA mA ;
messageA mB ;
aa.submit(mA);
aa.submit(mB);
}
可以帮助编译(这可以解释第22行的编译器错误)。
或者您可以更改提交方法的原型以接受const引用而不是非const引用。
注意:仍然没有编译器,所以试图对你的代码进行大脑调试...... :-P ......
答案 1 :(得分:1)
Something* smth1 = ((Base<Something> *)d)->createBase<Something>();
上面的代码工作正常。