【问题标题】:c++ class with template cannot find its constructor带有模板的c ++类找不到它的构造函数
【发布时间】:2009-03-13 20:05:13
【问题描述】:

我有一个我不太明白的问题。我有一个类节点。

template<class T>
class node {
protected:
    T _data;
public:
    node(T data);   
};

这是在“node.h”文件中。在“node.cpp”文件中,有这个构造函数:

#include "node.h"

template<class T>
node<T>::node (T data) {
    _data = data;
}

虽然编译器没有发现错误,但链接器 (ld) 告诉我:

/usr/bin/ld:未定义符号:

节点::node(int)

奇怪的部分...如果我将构造函数从 .cpp 移动到 .h 文件,一切正常。问题出在哪里?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    问题在于模板不是类——您通常不会将它们写在两个单独的文件中。模板类是编译器用来生成类的代码。因此,您的实现代码需要有效地内联,即在您发现的标头中。

    关于为什么必须这样的更完整解释,请参阅C++ FAQ Lite

    【讨论】:

      【解决方案2】:

      作为一般规则,您必须将所有模板成员放在头文件中。模板是按使用的基础编译的,因此无论在哪里使用,都需要提供整个定义。将代码放在头文件中就可以解决这个问题。

      您可以将模板定义放入 CPP 文件中的唯一情况是该模板只能在该 CPP 文件中使用。原因是它符合整个定义可用于编译的标准。

      将 node.cpp 的内容移动到 node.h 将解决问题。

      奇怪的场景

      同样,您也可以将所有内容放入 CPP 文件并包含 CPP 文件。 C++ 在这方面很灵活。我只提到这一点是因为我以前见过。当它撞到我的桌子顶部时,我真的把下巴擦伤了。

      【讨论】:

      • 如果您永远不会在其他地方调用它们,您也可以将非模板化类的模板化成员函数放入 cpp 文件中(所以强制执行,它们应该是私有的,但它们不会必须)。
      【解决方案3】:

      当您使用 node&lt;int&gt; 时,您很可能没有包含node.cpp。因此编译器无法实例化node&lt;int&gt;::node&lt;int&gt; 构造函数。通常你把所有的模板代码,包括方法的所有实现,放在头文件中,或者包含在头文件中。

      【讨论】:

        【解决方案4】:

        普遍接受的做法是将所有实现放在 .h 文件中,以便可以根据需要从模板生成类。

        如果您提前知道您的模板将使用哪些类型进行实例化,您或许可以作弊。只需确保您的 .cpp 包含您需要的每种类型和方法的用例。用例位于模板代码之后,这一点很重要。例如。对于“node.cpp”,使用

        #include "node.h"
        
        template<class T>
        node<T>::node (T data) {
            _data = data;
        }
        
        void dummy(void)
        {
            node<int> intnode(0);
            node<double> doublenode(0.0);
        }
        

        【讨论】:

          【解决方案5】:
          // You can put templates declaration in header and definition in source  
          // node.h or wherever you include file gets included
          extern template class node<int>;
          
          // node.cpp or where ever source file you want to use it
          // But use it only once for each type of generated class
          template class node<int>;
          

          【讨论】:

            【解决方案6】:

            除非有对该函数的调用,否则编译器不会输出任何代码,链接器也不会找到它。

            你应该把函数放在它所属的头文件中。

            【讨论】:

            • 我还是不明白。为什么模板不能是一个类,具有单独的标题和源代码?假设我想编写自己的 List .. 是否必须将每个 List 方法包含到头文件中?
            • 是的,这是最常见的方式。您也可以在 List.h 的底部#include "List.cpp"。
            • 好的。我发现将所有内容都包含在头文件中很奇怪 - 实际代码比问题中的几行长一点(它是二叉搜索树)。
            • 编译器必须为每种可能的数据类型生成不同的机器代码,但除非它知道需要哪些类型,否则它不能这样做。您不希望它为每种可能的数据类型编写代码...(!)
            【解决方案7】:

            隐式实例化已关闭,你需要

            template class node<int>;
            

            在您的代码中的某处(可能是 node.cpp)

            编辑:不好的答案,可能不是这样。

            【讨论】:

            • 如果您认为这是一个错误的答案,您可以在被否决之前将其删除。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-06-17
            • 2017-10-20
            • 2015-08-04
            • 2021-08-09
            • 2021-03-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多