我有一个问题,我真的不明白。我有一个Node节点。
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:未定义的符号:
节点&lt; INT&GT; ::节点(int)的
奇怪的部分......如果我将构造函数从.cpp移动到.h文件,一切正常。问题在哪里?
答案 0 :(得分:23)
问题是模板不是类 - 您通常不会将它们写在两个单独的文件中。模板类是编译器用于生成类的代码。因此,您的实现代码需要有效内联,即在您发现的标题中。
要更全面地解释为什么必须采用这种方式,请参阅C++ FAQ Lite。
答案 1 :(得分:13)
作为一般规则,您必须将所有模板成员放在头文件中。模板是在使用的基础上编译的,因此整个定义需要在任何使用它们的地方都可用。将代码放在头文件中将解决该问题。
只有在CPP文件中使用模板时,才能将模板定义放在CPP文件中。原因是它符合整个定义可用于编译的标准。
将node.cpp的内容移动到node.h将解决问题。
奇怪的情景
然后,您还可以将所有内容放入CPP文件中并包含CPP文件。 C ++以这种方式很灵活。我只提到这个,因为我之前见过。当我的下颚撞到我的桌子顶部时,我的下巴确实受伤了。
答案 2 :(得分:1)
当您使用 node<int>
时,您很可能不会包含node.cpp。因此,编译器无法实例化node<int>::node<int>
构造函数。通常,您将所有模板代码(包括方法的所有实现)放在头文件中,或者包含在其中的内容。
答案 3 :(得分:1)
普遍接受的做法是将所有实现放在.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);
}
答案 4 :(得分:1)
// 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>;
答案 5 :(得分:0)
除非调用该函数,否则编译器不会输出任何代码,链接器也无法找到它。
您应该将该函数放在它所属的标题中。
答案 6 :(得分:0)
隐式实例化已关闭,您需要
template class node<int>;
代码中的某处(可能是node.cpp)
编辑:糟糕的答案,情况可能并非如此。