请求成员`...'在g ++中是不明确的 [英] request for member `...' is ambiguous in g++

查看:197
本文介绍了请求成员`...'在g ++中是不明确的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到以下编译错误在我的一个类,使用gcc 3.4.5(mingw):

  src / ModelTester / CModelTesterGui.cpp:1308:error:对成员addListener的请求是不明确的
include / utility / ISource.h:26:error:candidates are:void utility :: ISource< T> (utility :: IListener< T> *)[with T = const SConsolePacket&]
include / utility / ISource.h:26:error:void实用程序:: ISource< T& ; T> *)[with T = const SControlPacket&]

希望你能看到 ISource< T> 是一个模板接口,只是指示对象可以是具有某种匹配类型 IListener< T& c $ c>。所以,有一个令人讨厌的事情是这样的想法,由于某些原因,功能是模糊的,当我可以告诉,他们不是。对于不同的输入类型 IListener< const SConsolePacket&> addListener() > IListener< const SControlPacket&> 。用法是:

  m_controller-> addListener(m_model); 

其中 m_model code> 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 ,并且通过调用 addListener(m_model)编译器应该明白我调用上面两个函数的第二个。



我甚至尝试投入 m_model

  m_controller-> addListener(
static_cast< IListener< const SControlPacket&> *(m_model));

但仍会得到该错误。我不能为我的生活看看这些功能是如何含糊的。任何人都可以了解这个问题吗?



我知道如何通过这样做来强制函数不模糊:

  m_controller-> ISource< const SControlPacket& ; :: addListener(m_model); 

我只是觉得这是非常不可读的,我不想这样做。 / p>

编辑...只是开玩笑。这显然不能解决这个问题,因为它导致链接器错误:

  CModelTesterGui.cpp:1312:undefined引用` 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是不明确的,因为在查找名称,它在两个不同的基类范围中查找函数。在这种情况下,查找是不明确的 - 它们不会彼此重载。修复将为每个成员名称使用一个使用声明。 Lookup将在 C 的范围内找到名称,不再查找:

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

现在,调用会找到两个函数,做重载解析, c $ c> int 将适合。对你的代码执行,这将意味着你必须做类似下面的事情

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

现在,这两个名称在同一范围内,现在他们可以重载对方。查找现在将停在控制器类,而不是进一步进入两个基类分支。


I'm getting the following compile error in one of my classes, using 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&]

Hopefully you can see that ISource<T> is a template interface that just indicates that the object can be an informer for an object that is of some matching type IListener<T>. So the thing that has me irked is this idea that for some reason functions are ambiguous when, as far as I can tell, they are not. The addListener() method is overloaded for different input types IListener<const SConsolePacket&> and IListener<const SControlPacket&>. The usage is:

m_controller->addListener( m_model );

Where m_model is a pointer to an IRigidBody object, and IRigidBody inherits only from IListener< const SControlPacket& > and definately not from IListener< const SConsolePacket& >

As a sanity check, I used doxygen to generate the class hierarchy diagram and doxygen agrees with me that IRigidBody does not derive from IListener< const SConsolePacket& >

Evidently my understanding of inheritence in c++ is not exactly correct. I'm under the impression that IListener<const SControlPacket&> and IListener<const SConsolePacket&> are two different types, and that the function declarations

addListener(IListener<const SConsolePacket&>* listener)

and

addListener(IListener<const SControlPacket&>* listener)

declare two separate functions that do two separate things depending on the (distinct) different type of the parameter that is input. Furthermore, I'm under the impression that a pointer to an IRigidBody is also a pointer to an IListener<const SControlPacket&> and that by calling addListener( m_model ) the compiler should understand that I'm calling the second of the above two functions.

I even tried casting m_model like this:

m_controller->addListener(
        static_cast<IListener<const SControlPacket&>*>(m_model) );

but still get that error. I cannot for the life of me see how these functions are ambiguous. Can anyone shed light on this issue?

P.S. I know how to force the function to be un-ambiguous by doing this:

m_controller->ISource<const SControlPacket&>::addListener( m_model );

I just happen to think that is terribly unreadible and I would prefer not to have to do that.

Edit... just kidding. That apparently doesn't fix the problem as it leads to a linker error:

CModelTesterGui.cpp:1312: undefined reference to `utility::ISource<aerobat::SControlPacket const&>::addListener(utility::IListener<SControlPacket const&>*)'

解决方案

Looks like your situation is like this:

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
}

The second call to f is ambiguous, because in looking up the name, it finds functions in two different base class scopes. In this situation, the lookup is ambiguous - they don't overload each other. A fix would be to use a using declaration for each member name. Lookup will find names in the scope of C and don't lookup further:

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

Now, the call would find two functions, do overload resolution, and find that the one taking int will fit. Carried over to your code, it would mean that you have to do something like the following

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

Now, the two names are in the same scope, and now they can overload each other. Lookup will now stop at the controller class, not diving further into the two base-class branches.

这篇关于请求成员`...'在g ++中是不明确的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆