其他分享
首页 > 其他分享> > c – 请求成员`…’在g中是不明确的

c – 请求成员`…’在g中是不明确的

作者:互联网

我在我的一个类中使用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>的对象的informer.让我烦恼的是这个想法,由于某种原因,功能是模棱两可的,据我所知,它们不是.对于不同的输入类型,重载addListener()方法IListener< const SConsolePacket&>和IListener< const SControlPacket&>.用法是:

m_controller->addListener( m_model );

其中m_model是指向IRigidBody对象的指针,而IRigidBody仅继承自IListener< const SControlPacket& &GT并且肯定不是来自IListener< const SConsolePacket& &GT 作为一个完整性检查,我使用doxygen来生成类层次结构图,并且doxygen同意我IRigidBody不是从IListener得到的< const SConsolePacket& &GT 显然,我对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&>*)'

解决方法:

看起来你的情况是这样的:

struct A {
  void f();
};

struct B {
  void f(int);
};

struct C : A, B { };

int main() { 
  C c; 
  c.B::f(1); // not ambiguous
  c.f(1);    // ambiguous
}

对f的第二次调用是不明确的,因为在查找名称时,它会在两个不同的基类范围中查找函数.在这种情况下,查找是不明确的 – 它们不会相互过载.修复方法是为每个成员名称使用using声明.查找将在C的范围内找到名称,不要进一步查找:

struct C : A, B { using A::f; using B::f; };

现在,调用将找到两个函数,执行重载解析,并发现采用int的函数将适合.继承您的代码,这意味着您必须执行以下操作

struct controller : ISource<const SConsolePacket&>, ISource<const SControlPacket&> {
  using ISource<const SConsolePacket&>::addListener;
  using ISource<const SControlPacket&>::addListener;
};

现在,这两个名称在同一范围内,现在它们可以相互重载. Lookup现在将停在控制器类,而不是进一步深入两个基类分支.

标签:ambiguous,c,gcc,g
来源: https://codeday.me/bug/20190928/1829199.html