Why do I get "unresolved external symbol" errors when using templates?

When I write C++ code for a class using templates and split the code between a source (CPP) file and a header (H) file, I get a whole lot of "unresolved external symbol" errors when it comes to linking the final executible, despite the object file being correctly built and included in the linking. What's happening here, and how can I fix it?

82025 次浏览

模板化的类和函数在使用之前不会实例化,通常是在单独的。Cpp 文件(例如程序源文件)。使用模板时,编译器需要该函数的完整代码,以便能够使用适当的类型生成正确的函数。但是,在这种情况下,该函数的代码在模板的源文件中有详细说明,因此不可用。

因此,编译器只是假设它在其他地方定义,并且只插入对模板化函数的调用。在编译模板的源文件时,程序源代码中使用的特定模板类型并没有被使用,因此它仍然不会生成函数所需的代码。这将导致未解析的外部符号。

现有的解决办法是:

  1. 包括... 的全部定义 中的成员函数 模板的头文件,而没有 模板的源文件,
  2. 中定义所有成员函数 模板的源文件 “ inline” (更新: [这在 Visual Studio 2017 + 上无法工作]) ,或
  3. 定义成员 模板源代码中的函数 “出口”关键字。 不幸的是,这并不受支持 (更新: 从 C + + 11开始,这已经从标准中删除了)

当编译器试图在程序源代码中构建类型化函数时,1和2基本上都是通过让编译器访问模板化函数的完整代码来解决这个问题的。

另一种选择是将代码放在 cpp 文件中,并在同一 cpp 文件中添加模板的显式实例化,其中包含您希望使用的类型。如果您事先知道只会针对几种类型使用它,那么这种方法非常有用。

对于包含.h 文件的每个文件,应该同时插入以下两行:

#include "MyfileWithTemplatesDeclaration.h"
#include "MyfileWithTemplatesDefinition.cpp"

样本

#include "list.h"
#include "list.cpp" //<---for to fix bug link err 2019






int main(int argc, _TCHAR* argv[])
{
list<int> my_list;
my_list.add_end(3);
.
.
}

另外,不要忘记将声明类放置在 Centinel 常量中

#ifndef LIST_H
#define LIST_H
#include <iostream>
.
.
template <class T>
class list
{
private:
int m_size,
m_count_nodes;
T m_line;
node<T> *m_head;
public:
list(void);
~list(void);
void add_end(T);
void print();
};
#endif