关于c ++:为什么在使用模板时会出现“未解析的外部符号”错误?

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

本问题已经有最佳答案,请猛点这里访问。

当我使用模板为类编写C++代码并在源(CPP)文件和报头(H)文件之间拆分代码时,在连接最终执行时,会得到大量的"未解决的外部符号"错误,尽管对象文件被正确地构建并包含在链接中。这里发生了什么事,我怎么修理?


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

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

可用于此目的的解决方案是:

  • 包括对中的成员函数模板的头文件模板的源文件,
  • 在中定义所有成员函数模板的源文件为"内联",或
  • 定义成员模板源中的函数使用"export"关键字。很遗憾,这不受支持通过很多编译器。(Update:这已经从C++ 11中的标准中删除)。
  • 当编译器试图在程序源代码中构建类型化函数时,1和2都通过赋予它对模板化函数的完整代码的访问权,基本上解决了这个问题。


    另一个选项是将代码放在cpp文件中,并在同一cpp文件中添加模板的显式实例化,该模板具有您希望使用的类型。如果你知道你只会将它用于一些你事先知道的类型,那么这是很有用的。


    对于包含.h文件的每个文件,应插入两行:

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

    样品

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #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常量中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #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