【发布时间】:2010-11-21 17:37:09
【问题描述】:
使用 gcc 3.4.5 (mingw) 在我的一个类中出现以下编译错误:
src/ModelTester/CModelTesterGui.cpp:1308: error: request for member `addListener' is ambiguous
include/utility/ISource.h:26: error: candidates are: void utility::ISource<T>::addListener(utility::IListener<T>*) [with T = const SConsolePacket&]
include/utility/ISource.h:26: error: void utility::ISource<T>::addListener(utility::IListener<T>*) [with T = const SControlPacket&]
希望您能看到ISource<T> 是一个模板接口,它只是表明该对象可以是某个匹配类型IListener<T> 的对象的告密者。所以让我恼火的是这样一个想法,即由于某种原因,函数是模棱两可的,据我所知,它们不是。 addListener() 方法针对不同的输入类型IListener<const SConsolePacket&> 和IListener<const SControlPacket&> 进行了重载。用法是:
m_controller->addListener( m_model );
其中m_model 是指向IRigidBody 对象的指针,而IRigidBody 仅继承自IListener< const SControlPacket& >,并且绝对不是来自IListener< const SConsolePacket& >
作为健全性检查,我使用 doxygen 生成类层次结构图,doxygen 同意我的观点,IRigidBody 不是从 IListener< const SConsolePacket& > 派生的
显然我对 C++ 中继承的理解并不完全正确。我的印象是IListener<const SControlPacket&> 和IListener<const SConsolePacket&> 是两种不同的类型,函数声明
addListener(IListener<const SConsolePacket&>* listener)
和
addListener(IListener<const SControlPacket&>* listener)
声明两个独立的函数,它们根据输入参数的(不同的)不同类型做两件不同的事情。此外,我的印象是指向IRigidBody 的指针也是指向IListener<const SControlPacket&> 的指针,并且通过调用addListener( m_model ),编译器应该明白我正在调用上述两个函数中的第二个。
我什至尝试像这样投射m_model:
m_controller->addListener(
static_cast<IListener<const SControlPacket&>*>(m_model) );
但仍然出现该错误。我一生都看不到这些功能是如何模棱两可的。谁能解释一下这个问题?
附:我知道如何通过这样做来强制函数明确:
m_controller->ISource<const SControlPacket&>::addListener( m_model );
我只是碰巧认为这非常不可读,我宁愿不必这样做。
编辑...开个玩笑。这显然不能解决问题,因为它会导致链接器错误:
CModelTesterGui.cpp:1312: undefined reference to `utility::ISource<aerobat::SControlPacket const&>::addListener(utility::IListener<SControlPacket const&>*)'
【问题讨论】:
-
SControlPacket和SConsolePacket是什么关系?
-
你能补充一下为什么最后一行
m_controller->ISource<const SControlPacket&>::addListener( m_model );消除了通话的歧义吗?如果函数被重载,它们应该在同一个类中。这些函数是在哪里声明的? -
@GRB 没有关系。两者都是从无到有的结构。 @litb 我错了。它使它可以编译,但是当链接器尝试查找纯虚拟的 ISource<...>::addListener(...) 时,结果会导致链接错误。现在我很困惑。当您说声明时,我假设您的意思是已定义。它们在派生自 IController 的具体类中定义。
-
@cheshirekow,我的意思是已声明,未定义。执行“a.B::f”会禁止虚拟调用机制。然后,如果您这样调用它,则必须存在纯虚函数的定义。对于名称查找,只有声明很重要。在这种情况下,使用声明可以阻止这些歧义。
-
@litb,知道了。你很准。也感谢您的回答!