代码之家  ›  专栏  ›  技术社区  ›  dlanod

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

  •  119
  • dlanod  · 技术社区  · 16 年前

    当我使用模板为类编写C++代码并将代码拆分为源(CPP)文件和头(H)文件时,在链接最终可执行文件时,我会遇到很多“未解决的外部符号”错误,尽管目标文件已正确构建并包含在链接中。这里发生了什么,我该怎么解决?

    3 回复  |  直到 16 年前
        1
  •  106
  •   dlanod    11 年前

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

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

    可用于此的解决方案是:

    1. 包括以下内容的完整定义 成员函数在 模板的头文件,没有 模板的源文件,
    2. 定义中的所有成员函数 模板的源文件为 “内联” (更新:[这在Visual Studio 2017+上不起作用]),或
    3. 定义成员 模板源代码中的函数 使用“export”关键字。 很遗憾,这不受支持 许多编译器。 (更新: this has been removed from the standard as of C++11 .)

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

        2
  •  12
  •   shoosh    16 年前

    另一种选择是将代码放入cpp文件,并在同一cpp文件中使用您期望使用的类型添加模板的显式实例化。如果你知道你只会把它用于你预先知道的几种类型,这很有用。

        3
  •  -2
  •   totem_motorist    12 年前

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