文件main2.cpp:
#include "poly2.h"
int main(){
Poly<int> cze;
return 0;
}
文件poly2.h:
template <class T>
class Poly {
public:
Poly();
};
文件poly2.cpp:
#include "poly2.h"
template<class T>
Poly<T>::Poly() {
}
编译时出错:
src$ g++ poly2.cpp main2.cpp -o poly
/tmp/ccXvKH3H.o: In function `main':
main2.cpp:(.text+0x11): undefined reference to `Poly<int>::Poly()'
collect2: ld returned 1 exit status
我正在尝试编译上面的代码,但在编译期间有错误。使用模板参数编译构造函数应该修复什么?
答案 0 :(得分:4)
完整的模板代码必须出现在一个文件中。您不能像使用普通类一样在多个文件之间分隔接口和实现。为了解决这个问题,许多人在标题中编写类定义,在另一个文件中编写实现,并在头文件的底部包含实现。例如:
Blah.h:
#ifndef BLAH_H
#define BLAH_H
template<typename T>
class Blah {
void something();
};
#include "Blah.template"
#endif
Blah.template:
template<typename T>
Blah<T>::something() { }
预处理器将等同于Blah.template
内容的Blah.h
内容的复制粘贴,编译器看到它时所有内容都在一个文件中,并且每个人都是高兴。
答案 1 :(得分:1)
如果在C ++中使用模板,则使用模板的所有函数实现都需要在头文件中。或者您的编译器找不到类型的正确(或任何)版本。
有关详细信息,请参阅this个问题。
答案 2 :(得分:1)
如何定义模板类的古老问题。模板实际上不是代码,它是您稍后用于定义代码的模板。因此,有两种可能的解决方案,如果您知道将要使用的某些类型的Poly
,则可以在.cpp文件中定义它们。
#include "poly2.h"
Poly<int>;
template<class T>
Poly<T>::Poly() {
}
或者您可以将所有模板定义和声明放在头文件中。我喜欢做的是创建一个单独的.hpp文件并将定义放在那里。所以我会这样做:
poly2.h
template <class T>
class Poly {
public:
Poly();
};
#include "poly2-impl.hpp"
聚2- impl.hpp
template<class T>
Poly<T>::Poly() {
}
关于模板的事情是,您可以将头文件包含在多个翻译文件中,而不会出现先前定义的错误。
有关详细信息,请参阅此处:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
答案 3 :(得分:0)
通常,编译源文件所需的只是一堆函数声明,稍后可以在定义中进行链接。
不幸的是,当模板进入组合时,它并不那么简单。由于模板在使用时必须实例化,因此在使用时它们的定义必须是可见的。 main2.cpp
无法看到Poly<int>::Poly()
的定义,因此未对此函数进行实例化。因此它从目标文件中丢失而且不可链接。
您应该在头文件中编写功能模板,以便它们可以在您使用它们的所有翻译单元中使用。它并不理想,但没有export
(或执行显式实例化),你可以做很多事情。