简体   繁体   English

为什么我的模板函数指针出现链接器错误?

[英]Why am I getting a Linker error with template function pointer?

I have a class EventMgr which has a template function to register a listener. 我有一个EventMgr类,该类具有用于注册侦听器的模板功能。 But, when I register a listener, linker gives me a " error LNK2019: unresolved external symbol ". 但是,当我注册一个侦听器时,链接器给我一个“ 错误LNK2019:无法解析的外部符号 ”。

Appetizer code: 开胃菜代码:

class EventMgr {

 template< class T, class EvenT>
 void RegisterListener(T* listener, int EventType, void (T::*MemFunc)(EvenT*) );
}

SoundMgr(which is a listener) tries to register for event: SoundMgr(是一个侦听器)尝试注册事件:

SoundMgr::SoundMgr(void)
{
  EventManager::GetInstance()->RegisterListener(this, 1, (&SoundMgr::handleBulletFired));
}

I'm not sure why it won't link. 我不确定为什么它不会链接。 Why can it not find the reference types ? 为什么找不到引用类型?

If you simply declared the template in a .h file and the implementation is instead in a .cpp file then this is the error you will get, because a C++ compiler works one compile unit at a time. 如果仅在.h文件中声明模板,而在.cpp文件中声明实现,则将出现此错误,因为C ++编译器一次只工作一个编译单元。 When the compiler finds your code calling a template function that has been just declared it will assume that the concrete instantiation will be done by some other compilation unit (there is no way the compiler can know where to find the .cpp file for that function... the compiler only sees one .cpp and all the included .h at a time). 当编译器找到调用刚刚声明的模板函数的代码时,它将假定具体实例化将由其他某个编译单元完成(编译器无法知道在哪里可以找到该函数的.cpp文件。 ..编译器一次只能看到一个.cpp和所有包含的.h)。

If the template parameters are from a well known list you can simply request the all explicit implementations you know that will be needed for the program in the .cpp. 如果模板参数来自一个众所周知的列表,您可以简单地请求所有您知道的.cpp中程序所需的显式实现。

For example if you have a template function 例如,如果您具有模板功能

template<typename T>
T foo(T x)
{
   ...
}

and you know are just going to need int foo(int); 而且您知道只需要int foo(int); and string foo(string); string foo(string); then it's fine to use just the declaration in the .h, provided you also add two lines in the .cpp saying: 那么就可以只使用.h中的声明,只要您还在.cpp中添加两行即可:

template<> int foo(int);
template<> string foo(string);

By doing that you are telling the compiler about what specialization to build. 这样,您就告诉编译器要构建什么专业。 If you later end up using other specializations (eg vector<int> foo(vector<int>) ) then you must also add this explicit instantiation in the .cpp file of the template. 如果以后您最终使用其他专业化名称(例如, vector<int> foo(vector<int>) ),则还必须在模板的.cpp文件中添加此显式实例化。

However in your example looking at the code I guess that you don't know in advance which kind of events will be defined and so this explicit instantiation cannot be done. 但是,在查看代码的示例中,我想您可能事先不知道将定义哪种事件,因此无法执行此显式实例化。

The other solution is to simply put the whole template implementation in the .h file instead of separating declaration from implementation. 另一种解决方案是将整个模板实现简单地放在.h文件中,而不是将声明与实现分开。 This sometimes can be not trivial because requires you to expose more implementation details probably introducing more dependencies. 有时这并非易事,因为需要您公开更多的实现细节,可能会引入更多的依赖关系。

This probably means that RegisterListener is not actually implemented anywhere. 这可能意味着RegisterListener实际上并没有在任何地方实现。 As it is a template function, you should implement it in the header. 由于它是模板函数,因此应在标头中实现它。

Try the following in the header. 尝试在标题中执行以下操作。

template< class T, class EvenT > 
void RegisterListener(T* listener, int EventType, void (T::MemFunc)(EvenT) ) { }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM