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++ c++;具有模板的类找不到其构造函数_C++_Templates - Fatal编程技术网

C++ c++;具有模板的类找不到其构造函数

C++ c++;具有模板的类找不到其构造函数,c++,templates,C++,Templates,我有个问题我不太明白。我有一个类节点 template<class T> class node { protected: T _data; public: node(T data); }; 模板 类节点{ 受保护的: T_数据; 公众: 节点(T数据); }; 这在“node.h”文件中。在“node.cpp”文件中,有一个构造函数: #include "node.h" template<class T> node<T>::node

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

template<class T>
class node {
protected:
    T _data;
public:
    node(T data);   
};
模板
类节点{
受保护的:
T_数据;
公众:
节点(T数据);
};
这在“node.h”文件中。在“node.cpp”文件中,有一个构造函数:

#include "node.h"

template<class T>
node<T>::node (T data) {
    _data = data;
}
#包括“node.h”
模板
node::node(T数据){
_数据=数据;
}
虽然编译器没有发现错误,但链接器(ld)告诉我:

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

节点::节点(int)


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

一般来说,必须将所有模板成员放在头文件中。模板是在使用的基础上编译的,因此无论在何处使用,都需要提供完整的定义。将代码放入头文件将解决该问题

唯一可以将模板定义放入CPP文件的时间是该模板仅在该CPP文件中使用的时间。原因是它符合整个定义可供编译的标准

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

奇怪的场景


然后,您还可以将所有内容都放在CPP文件中,并包括CPP文件。C++是这样灵活的。我之所以提到这一点,是因为我以前见过这样的人。实际上,当它撞到我的桌面时,我的下巴被撞伤了。

当你使用
节点时,你很可能没有包括node.cpp。因此,编译器无法实例化
节点::节点
构造函数。通常,您会将所有模板代码(包括方法的所有实现)放入头文件或其中包含的内容。

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


您应该将函数放在它所属的头文件中。

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


有关为什么必须采用这种方式的更全面的解释,请参见。

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

template class node<int>;
模板类节点;
代码中的某个地方(node.cpp可能)


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

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

如果您提前知道模板将使用哪种类型进行实例化,您可能会有点作弊。只要确保您的.cpp为您需要的每种类型和方法都包含一个用例。用例放在模板代码之后是很重要的。例如,对于“node.cpp”,使用

#包括“node.h”
模板
node::node(T数据){
_数据=数据;
}
虚空假人(虚空)
{
节点intnode(0);
节点双节点(0.0);
}
//您可以将模板声明放在标题中,将定义放在源代码中
//h或包含文件的任何位置
外部模板类节点;
//node.cpp或要使用它的任何源文件
//但对生成的每种类型的类只使用一次
模板类节点;

我还是不明白。为什么模板不能是一个类,有单独的头和源代码?假设我想写我自己的清单。。是否必须将每个列表方法都包含到头文件中?是的,这是最常见的方法。您还可以在列表的底部包含“List.cpp”。h.ok。我发现将所有内容都包含在头文件中很奇怪-实际代码比问题中的几行长一点(这是一个二元搜索树)。编译器必须为每种可能的数据类型生成不同的机器代码,但除非它知道需要哪些类型,否则它无法做到这一点。您不希望它为每种可能的数据类型生成代码…(!)如果您永远不会在其他地方调用非模板化类的模板化成员函数,您也可以将其放入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);
}
// 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>;