我在调用模板类时遇到问题。 我声明了一个新的类型名称Array,它是一个模板;
在.hpp文件中:
template <typename T>
class Array
{
public:
Array();
};
在.cpp文件中:
template <typename T>
Array<T>::Array()
{
//Do something
}
主要:
Array<int> arr;
我收到了Linkage错误:未解析的外部符号给ctor。
任何想法?
答案 0 :(得分:59)
模板函数(包括成员函数)必须完全写在头文件中。这意味着如果您有模板类,则其实现必须完全在头文件中。这是因为编译器需要访问整个模板定义(而不仅仅是签名)才能为模板的每个实例化生成代码。
答案 1 :(得分:8)
同时放置模板声明和模板功能 头文件中的定义。大多数C ++编译器不容易支持模板的单独编译模型,
答案 2 :(得分:6)
如果模板化函数的定义在使用它的位置不可见(即不在标题或相同的CPP文件中),则需要tell the compiler which instantiations to make。
答案 3 :(得分:4)
您遇到的问题是您在.cpp文件中隐藏了构造函数的定义。此定义适用于所有类型T
,包括T
作为您使用的int
,但实际上不提供任何定义,因为它仍然只是一个声明。<登记/>
链接器找不到符号Array<int>::Array()
。
现在,您可以添加如下所示的行:
Array<int> arr1;
到Array.cpp文件的末尾,这使编译器实例化成为链接器正在寻找的正确定义。但是,这仅提供一个定义,Array<int>
而不是其他定义。
此解决方案可行,直到您需要Array
其他模板参数,例如double
,此时您需要添加:
Array<double> arr2;
到您的Array.cpp文件的末尾 - 现在您可以看到这是不可持续的!
如果您需要使用C ++来处理将来可能需要的任何类型,现在是时候将ctor的定义(可能是所有其他成员函数)移到标题(并删除.cpp文件,因为它不会留下任何内容)。
答案 4 :(得分:1)
如上所述,在C ++模板中,新方法的过程是由编译器在编译时执行的,问题是它需要在那段时间内知道thm的所有定义,因此所有类/函数声明必须是ar h或hpp文件。
答案 5 :(得分:1)
另一个答案,只编译.cpp文件(不是主文件)并检查目标文件的大小,然后创建一个empty.cpp文件,然后编译该empty.cpp。最后比较两个目标文件的大小。您将看到它们具有相同的大小,这意味着您的.cpp文件对编译器没有任何意义,因此链接器无法找到任何内容。