请参阅此问题中有关实施模板的第一个答案.
具体来说,请注意这个引用
一个常见的解决方案是在头文件中编写模板声明,然后在实现文件(例如.tpp)中实现该类,并在头的末尾包含此实现文件.
我加粗了我最感兴趣的部分
..tpp文件的意义是什么?我尝试完全按照该页面中的建议进行操作.但后来,我将文件扩展名更改为任何随机乱码(如.zz或.ypp),它仍然有效!它应该工作吗?是否.tpp或任何其他扩展名是否重要?为什么不使用.cpp?
这是我很困惑的另一件事.
如果我的实现是用.cpp编写的,并且头文件定义了非模板化的函数,那么我只需要编译一次.cpp文件,对吧?至少在我改变.cpp文件中的内容之前.
但是,如果我有一个定义模板化函数的标题,并且我的实现是在一个带有随机时髦扩展的文件中,它是如何编译的?每次编译任何源代码#include
的头部时,编译的实现是什么?
Cur*_*ous 16
是否.tpp或任何其他扩展名是否重要?为什么不使用.cpp?
扩展名是什么并不重要,但不要使用,.cpp
因为它违反了约定(它仍然可以工作,但不要这样做; .cpp
文件通常是源文件).除此之外,它是您的代码库使用的问题.例如,I(和Boost代码库).ipp
用于此目的.
.tpp文件的意义是什么?
当您不希望包含模块接口的文件包含所有gory实现细节时,可以使用它.但是你不能在.cpp
文件中编写实现,因为它是一个模板.所以你尽力而为(不考虑明确的实例化等).例如
Something.hpp
#pragma once
namespace space {
template <typename Type>
class Something {
public:
void some_interface();
};
} // namespace space
#include "Something.ipp"
Run Code Online (Sandbox Code Playgroud)
Something.ipp
#pragma once
namespace space {
template <typename Type>
void Something<Type>::some_interface() {
// the implementation
}
} // namespace space
Run Code Online (Sandbox Code Playgroud)
我认为在头文件中编写定义以及在单独文件中实现的重点是节省编译时间,因此您只需编译一次实现,直到您进行一些更改
您不能将通用模板代码拆分为实现文件.您需要可见的完整代码才能使用模板,这就是您需要将所有内容放在头文件中的原因.有关更多信息,请参阅为什么模板只能在头文件中实现?
但是如果实现文件有一些看似时髦的文件扩展名,那么在编译方面它是如何工作的呢?它是否像在cpp中实现一样高效?
你不编译.tpp
,.ipp
,-inl.h
,等文件.它们就像头文件一样,只是它们只包含在其他头文件中.您只编译源(.cpp
,.cc
)文件.
文件扩展名对预处理程序毫无意义; .h
两者都没有什么神圣之处.这只是惯例,所以其他程序员知道并理解文件包含的内容.
预处理器允许您将任何文件包含到任何翻译单元中(这是一个非常生硬的工具).像这样的扩展只是帮助澄清应该包括在哪里.