Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我会得到;未解析的外部符号“;使用模板时出错? 当我使用模板编写类的C++代码,并在源(CPP)文件和头(H)文件之间拆分代码时,当连接最终的执行时,尽管对象文件被正确地构建并包含在链接中,但是我得到了大量的“未解决的外部符号”错误。这里发生了什么,我如何修复它?_C++_Templates_Linker - Fatal编程技术网

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

为什么我会得到;未解析的外部符号“;使用模板时出错? 当我使用模板编写类的C++代码,并在源(CPP)文件和头(H)文件之间拆分代码时,当连接最终的执行时,尽管对象文件被正确地构建并包含在链接中,但是我得到了大量的“未解决的外部符号”错误。这里发生了什么,我如何修复它?,c++,templates,linker,C++,Templates,Linker,模板化的类和函数在使用之前不会实例化,通常在单独的.cpp文件(例如程序源)中。使用模板时,编译器需要该函数的完整代码,以便能够使用适当的类型构建正确的函数。但是,在这种情况下,该函数的代码在模板的源文件中有详细说明,因此不可用 因此,编译器只是假设它是在别处定义的,并且只插入对模板函数的调用。在编译模板的源文件时,程序源中使用的特定模板类型没有在那里使用,因此它仍然不会生成函数所需的代码。这将导致无法解析的外部符号 可用于此的解决方案包括: 包括以下内容的完整定义: 中的成员函数 模板的头文件

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

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

可用于此的解决方案包括:

  • 包括以下内容的完整定义: 中的成员函数 模板的头文件,并且没有 模板的源文件
  • 定义中的所有成员函数 模板的源文件为 “内联”(更新:[这在Visual Studio 2017+上不起作用]),或
  • 定义成员 模板源中的函数 使用“导出”关键字。 不幸的是,这不受支持 由许多编译器编写。(更新:)

  • 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);
        .
        .
        } 
    
    #包括“list.h”
    
    #在(3)中包含“list.cpp”//您有键入错误。你可能指的是关键字,而不是键盘。我不认为将函数定义为“inline”会有什么帮助。您需要将它们放在标题中,或者使用您需要的类型显式实例化模板。您可能需要重新表述(2)。不知道你说的是什么“导出”关键字也提供了完整的定义。它可能以某种稍微编码的形式出现,比如编译器解析树,但它并没有很好地隐藏起来。当然,我想机器代码也不能很好地隐藏源代码。我也有同样的问题,但这并不能解决它。。。我不知道为什么这个答案被接受。包含成员函数的完整定义是可行的,但是,在我看来,它代表了我们的程序缺乏安全性,通常是一种糟糕的做法,会导致代码无组织。@johanneschaub litb如果所有内容都需要在头文件中(定义)那么
    .cpp
    文件有什么用呢?我认为这不是一个好主意。包含.cpp文件会发送错误的消息。如果希望用户同时包含这两个文件。把它们命名为code.h和code_impl.h或类似名称。我同意。几乎没有理由在源代码中包含一个.cpp文件,而且根据您的项目设置,这甚至可能会给编译器带来一个单独的头绪,也就是说,f********u表示模块化、重用、单一责任和关注点分离。。。而泛型编程的全部要点就是拥有泛型类,这些泛型类可以与您想要的任何类型一起使用,而模板类事先不知道它将用于什么?@jbx我是说,对于像
    basic\u string
    这样的东西,您只能将其与
    char
    wchar\u t
    一起使用,如果将所有实现放在头中是一个问题,在cpp中实例化它是一个选项。代码由你来指挥,而不是由你来指挥。在我看来,这违背了模板的全部观点。您的示例只是一个例外(如果只针对2种类型,那么应该使用重载编写,但这是另一个参数)。模板编程应该是关于创建一些独立于与之交互的类型而工作的东西,而不需要事先知道。预测这些类型将是什么与它的全部目的背道而驰。这只是一个“解决”痛苦的糟糕做法,但仅仅因为你可以,并不意味着你应该。@jbx错了。模板编程就是不要重复你自己。如果你写的东西恰巧是超一般的和美妙的,对你有好处,但这绝对不是必要的。如果它允许我只编写一个类或函数而不是2个,那么它就实现了它的目的。即使是标准容器也不是独立于类型的,它们依赖于诸如default c'tor和move c'tor之类的东西。你说这不是为了不重复你自己,然后在下一句话中你说如果它允许你只写一个类或函数istead of 2,它就实现了它的目的,那么,这怎么不是为了不重复你自己?如果每次需要将模板的头文件用于另一个新类型时都必须修改它,那么代码如何遵循打开-关闭原则。让我们承认,这是一个黑客,由于C++的限制,其中一个恼人的设计缺陷,像许多其他。
    #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