所以,我听说C ++模板不应该分成标题(.h)和源(.cpp)文件。
例如,这样的模板:
template <class T>
class J
{
T something;
};
这是真的吗?为什么会这样?
如果由于这个原因,我必须将声明和实现放在同一个文件中,我应该把它放在.h文件还是.cpp文件中?
答案 0 :(得分:26)
头。
这是因为模板在编译时实例化,而不是链接时,并且不同的翻译单元(大致相当于您的.cpp
文件)在链接时只相互“了解”。在编译时,标题往往被广泛“了解”,因为你在任何需要它们的翻译单元中#include
。
答案 1 :(得分:14)
你不能将模板化的类放入.cpp文件的原因是因为为了“编译”.cpp文件,你需要知道用什么类型来代替T.模板化的类(就像你的类J一样)没有足够的信息来编译。因此它必须全部在标题中。
如果您希望将实现分解为另一个文件以保持清洁,最佳做法是使用.hxx文件。像这样:在你的头文件里面,J.h,把:
#ifndef _J_H__
#define _J_H__
template <class T> class J{ // member definitions };
#include "j.hxx"
#endif // _J_H__
然后,在j.hxx中你将有
template <class T> J<T>::J() { // constructor implementation }
template <class T> J<T>::~J() { // destructor implementation }
template <class T> void J<T>::memberFunc() { // memberFunc implementation }
// etc.
最后在使用模板化类的.cpp文件中,让我们称之为K.cpp:
#include "J.h" // note that this always automatically includes J.hxx
void f(void)
{
J<double> jinstance; // now the compiler knows what the exact type is.
}
答案 2 :(得分:4)
是的,这是真的。声明和实现通常一起放入头文件中。一些编译器尝试使用export
关键字来允许它们分开,但是已经从C ++ 0x中删除了。查看this FAQ entry了解所有脏信息。
答案 3 :(得分:2)
如果您需要模板代码可供其他翻译单元(.cpp文件)使用,则需要将实现放在.h文件中,否则其他单元将无法实例化模板(展开它)根据他们使用的类型)。
如果模板函数仅在一个.cpp文件中实例化,则可以在那里定义它。当类具有作为模板的私有成员函数时(有时仅从实现文件调用,而不是类头文件),有时会发生这种情况。