对继承模板方法的模糊调用
Ambiguous call to inherited template method
我正在开发一个简单的事件系统来练习使用 stdlib。
我做了一个 EventEmitter<T>
class,它提供了 addListener(T)
和 emitEvent(T)
。
TestEmitter
class 扩展了 EventEmitter<int>
和 EventEmitter<std::string>
。 TestEmitter
class 有一个 emitTestEvent
方法调用 emitEvent(1337)
或 emitEvent(std::string("test"))
。
在 main() 中创建了一个 TestEmitter
的实例,并为 T=int 和 T=std::string 添加了两个侦听器。
我收到 4 个如下所示的错误:reference to ‘emitEvent’ is ambiguous
。 emitEvent
调用两次,addListener
调用两次。
这是完整的输出:
main.cpp: In member function ‘virtual void TestEmitter::emitTestEvent()’:
main.cpp:42:4: error: reference to ‘emitEvent’ is ambiguous
main.cpp:23:15: error: candidates are: void EventEmitter<T>::emitEvent(T) [with T = std::basic_string<char>]
main.cpp:23:15: error: void EventEmitter<T>::emitEvent(T) [with T = int]
main.cpp:45:4: error: reference to ‘emitEvent’ is ambiguous
main.cpp:23:15: error: candidates are: void EventEmitter<T>::emitEvent(T) [with T = std::basic_string<char>]
main.cpp:23:15: error: void EventEmitter<T>::emitEvent(T) [with T = int]
main.cpp: In function ‘int main(int, char**)’:
main.cpp:53:10: error: request for member ‘addListener’ is ambiguous
main.cpp:19:15: error: candidates are: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = std::basic_string<char>; EventEmitter<T>::Listener = std::function<void(std::basic_string<char>)>]
main.cpp:19:15: error: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = int; EventEmitter<T>::Listener = std::function<void(int)>]
main.cpp:57:10: error: request for member ‘addListener’ is ambiguous
main.cpp:19:15: error: candidates are: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = std::basic_string<char>; EventEmitter<T>::Listener = std::function<void(std::basic_string<char>)>]
main.cpp:19:15: error: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = int; EventEmitter<T>::Listener = std::function<void(int)>]
我很困惑为什么我会收到这个错误,编译器 (g++) 清楚地知道 T
是哪个调用的意思,但它不知道要调用哪个方法?
我可以通过在 emitEvent
调用前面加上 EventEmitter<int>::
和 EventEmitter<std::string>
来修复这些错误,但我不确定这是否是解决此问题的正确方法.
当编译器知道 T
的类型时,为什么对 emitEvent
和 addListener
的调用不明确?我该如何解决这个问题?
我希望我提供了足够的信息,如果没有让我知道。这是代码:
#include <list>
#include <map>
#include <string>
#include <functional>
#include <iostream>
template<typename T>
class EventEmitter {
private:
typedef std::function<void(T)> Listener;
protected:
std::list<Listener> listeners_;
public:
EventEmitter() {};
virtual ~EventEmitter() {};
virtual void addListener(Listener listener) {
listeners_.push_back(listener);
};
virtual void emitEvent(T event) {
typename std::list<Listener>::iterator it = listeners_.begin();
for(; it != listeners_.end(); ++it) {
(*it)(event);
}
};
};
class TestEmitter : public EventEmitter<int>, public EventEmitter<std::string> {
private:
int count_;
public:
TestEmitter() {};
virtual ~TestEmitter() {};
virtual void emitTestEvent() {
count_ = (++count_) % 2;
if(count_ == 0) {
EventEmitter<int>::emitEvent(1337);
}
else {
EventEmitter<std::string>::emitEvent(std::string("test"));
}
};
};
int main(int argc, char* argv[]) {
TestEmitter emitter;
emitter.addListener([](int event) {
std::cout << "Hello: " << event << std::endl;
});
emitter.addListener([](std::string event) {
std::cout << "Bye: " << event << std::endl;
});
for(int i = 0; i < 10; i++) {
emitter.emitTestEvent();
}
return 0;
}
谢谢:)
您的 class 继承了两个不同的 class。现在,有两种方法:EventEmitter::emitTestEvent 和 EventEmitter::emitTestEvent
应该叫哪个?这个本身就不清楚
您可以执行以下操作:
emitter.EventEmitter<int>::emitEvent(/* ... */);
但是,您可能会想太多您的设计...当您的 class 的用户调用 eventEmit 时,它应该做什么?然后,相应地设计您的 classes,以便它们提供这种行为。
编辑:
另一种解决方案可以通过using
找到,例如:
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
void foo(int) {cout << "A::foo";}
};
class B
{
public:
void foo(string) {cout << "B::foo";}
};
class C : public A, public B
{
public:
using A::foo;
using B::foo;
};
int main() {
C c;
c.foo(10);
c.foo("hi");
return 0;
}
我正在开发一个简单的事件系统来练习使用 stdlib。
我做了一个 EventEmitter<T>
class,它提供了 addListener(T)
和 emitEvent(T)
。
TestEmitter
class 扩展了 EventEmitter<int>
和 EventEmitter<std::string>
。 TestEmitter
class 有一个 emitTestEvent
方法调用 emitEvent(1337)
或 emitEvent(std::string("test"))
。
在 main() 中创建了一个 TestEmitter
的实例,并为 T=int 和 T=std::string 添加了两个侦听器。
我收到 4 个如下所示的错误:reference to ‘emitEvent’ is ambiguous
。 emitEvent
调用两次,addListener
调用两次。
这是完整的输出:
main.cpp: In member function ‘virtual void TestEmitter::emitTestEvent()’:
main.cpp:42:4: error: reference to ‘emitEvent’ is ambiguous
main.cpp:23:15: error: candidates are: void EventEmitter<T>::emitEvent(T) [with T = std::basic_string<char>]
main.cpp:23:15: error: void EventEmitter<T>::emitEvent(T) [with T = int]
main.cpp:45:4: error: reference to ‘emitEvent’ is ambiguous
main.cpp:23:15: error: candidates are: void EventEmitter<T>::emitEvent(T) [with T = std::basic_string<char>]
main.cpp:23:15: error: void EventEmitter<T>::emitEvent(T) [with T = int]
main.cpp: In function ‘int main(int, char**)’:
main.cpp:53:10: error: request for member ‘addListener’ is ambiguous
main.cpp:19:15: error: candidates are: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = std::basic_string<char>; EventEmitter<T>::Listener = std::function<void(std::basic_string<char>)>]
main.cpp:19:15: error: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = int; EventEmitter<T>::Listener = std::function<void(int)>]
main.cpp:57:10: error: request for member ‘addListener’ is ambiguous
main.cpp:19:15: error: candidates are: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = std::basic_string<char>; EventEmitter<T>::Listener = std::function<void(std::basic_string<char>)>]
main.cpp:19:15: error: void EventEmitter<T>::addListener(EventEmitter<T>::Listener) [with T = int; EventEmitter<T>::Listener = std::function<void(int)>]
我很困惑为什么我会收到这个错误,编译器 (g++) 清楚地知道 T
是哪个调用的意思,但它不知道要调用哪个方法?
我可以通过在 emitEvent
调用前面加上 EventEmitter<int>::
和 EventEmitter<std::string>
来修复这些错误,但我不确定这是否是解决此问题的正确方法.
当编译器知道 T
的类型时,为什么对 emitEvent
和 addListener
的调用不明确?我该如何解决这个问题?
我希望我提供了足够的信息,如果没有让我知道。这是代码:
#include <list>
#include <map>
#include <string>
#include <functional>
#include <iostream>
template<typename T>
class EventEmitter {
private:
typedef std::function<void(T)> Listener;
protected:
std::list<Listener> listeners_;
public:
EventEmitter() {};
virtual ~EventEmitter() {};
virtual void addListener(Listener listener) {
listeners_.push_back(listener);
};
virtual void emitEvent(T event) {
typename std::list<Listener>::iterator it = listeners_.begin();
for(; it != listeners_.end(); ++it) {
(*it)(event);
}
};
};
class TestEmitter : public EventEmitter<int>, public EventEmitter<std::string> {
private:
int count_;
public:
TestEmitter() {};
virtual ~TestEmitter() {};
virtual void emitTestEvent() {
count_ = (++count_) % 2;
if(count_ == 0) {
EventEmitter<int>::emitEvent(1337);
}
else {
EventEmitter<std::string>::emitEvent(std::string("test"));
}
};
};
int main(int argc, char* argv[]) {
TestEmitter emitter;
emitter.addListener([](int event) {
std::cout << "Hello: " << event << std::endl;
});
emitter.addListener([](std::string event) {
std::cout << "Bye: " << event << std::endl;
});
for(int i = 0; i < 10; i++) {
emitter.emitTestEvent();
}
return 0;
}
谢谢:)
您的 class 继承了两个不同的 class。现在,有两种方法:EventEmitter::emitTestEvent 和 EventEmitter::emitTestEvent
应该叫哪个?这个本身就不清楚
您可以执行以下操作:
emitter.EventEmitter<int>::emitEvent(/* ... */);
但是,您可能会想太多您的设计...当您的 class 的用户调用 eventEmit 时,它应该做什么?然后,相应地设计您的 classes,以便它们提供这种行为。
编辑:
另一种解决方案可以通过using
找到,例如:
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
void foo(int) {cout << "A::foo";}
};
class B
{
public:
void foo(string) {cout << "B::foo";}
};
class C : public A, public B
{
public:
using A::foo;
using B::foo;
};
int main() {
C c;
c.foo(10);
c.foo("hi");
return 0;
}