使用模板时,为什么会出现“未解析的外部符号”错误?

时间:2009-01-19 06:29:09

标签: c++ templates linker

当我使用模板为类编写C ++代码并在源(CPP)文件和标题(H)文件之间拆分代码时,在链接时会出现大量“未解析的外部符号”错误最终可执行,尽管目标文件正确构建并包含在链接中。这里发生了什么,我该如何解决?

3 个答案:

答案 0 :(得分:107)

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

由于所有这些,编译器只是假定它在别处定义并且仅将调用插入到模板化函数中。在编译模板的源文件时,程序源中使用的特定模板类型不会在那里使用,因此它仍然不会生成该函数所需的代码。这导致未解析的外部符号。

可用的解决方案是:

  1. 包括完整定义 中的成员函数 模板的头文件并没有 模板的源文件
  2. 定义所有成员函数 模板的源文件为 “内联”,或
  3. 定义成员 函数在模板的源代码中 使用“export”关键字。 不幸的是,这不受支持 很多编译器。(更新:this has been removed from the standard as of C++11。)
  4. 1和2基本上解决了这个问题,它允许编译器在尝试在程序源中构建类型化函数时访问模板化函数的完整代码。

答案 1 :(得分:12)

另一个选择是将代码放在cpp文件中,并在同一个cpp文件中添加模板的显式实例化,以及您希望使用的类型。如果你知道你只是提前将它用于你知道的几种类型,那么这很有用。

答案 2 :(得分:-2)

对于包含.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