为什么在实现头文件中定义的模板化函数和类时使用“tpp”文件?

新手上路,请多包涵

请参阅 此问题中有关实施模板的第一个答案。

具体来说,请注意此报价

一个常见的解决方案是在头文件中编写模板声明,然后在实现文件( 例如 .tpp )中实现类,并在头文件的末尾包含这个实现文件。

我将我最感兴趣的部分加粗。

.tpp 文件有什么意义?我尝试完全按照该页面中的建议进行操作,并且成功了。但后来,我将文件扩展名更改为任何随机乱码(如 .zz 或 .ypp),它仍然有效!它应该工作吗?它是 .tpp 还是任何其他扩展名是否重要?为什么不使用.cpp?

这是我感到困惑的另一件事。

如果我的实现是用 .cpp 编写的,并且头文件定义了非模板函数,那么我只需要编译 .cpp 文件一次,对吗?至少在我更改 .cpp 文件中的某些内容之前。

但是,如果我有一个定义模板函数的标头,并且我的实现在一个带有随机时髦扩展名的文件中,它是如何编译的? 每次 我编译任何源代码 #include s 所说的标题时,是否都会编译实现?

原文由 Manuel 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.9k
1 个回答

它是 .tpp 还是任何其他扩展名是否重要?为什么不使用.cpp?

扩展名是什么并不重要,但不要使用 .cpp 因为它违反约定(它仍然可以工作,但不要这样做; .cpp 文件通常是源文件)。除此之外,这取决于您的代码库使用什么。例如,我(和 Boost 代码库)为此目的使用 .ipp

.tpp 文件有什么意义?

当您不希望包含模块接口的文件包含所有血腥的实现细节时使用它。但是您不能在 .cpp 文件中编写实现,因为它是一个模板。所以你尽你所能(不考虑显式实例化等)。例如

东西.hpp

 #pragma once

namespace space {

template <typename Type>
class Something {
public:
    void some_interface();
};

} // namespace space

#include "Something.ipp"

东西.ipp

 #pragma once

namespace space {

template <typename Type>
void Something<Type>::some_interface() {
    // the implementation
}

} // namespace space


我认为在头文件中编写定义并在单独的文件中编写实现的全部目的是节省编译时间,以便您只编译一次实现,直到您进行一些更改

您不能将通用模板代码拆分为实现文件。您需要完整的代码可见才能使用模板,这就是为什么您需要将所有内容放在头文件中的原因。更多见 为什么模板只能在头文件中实现?

但是如果实现文件有一些看起来很时髦的文件扩展名,那么它在编译方面是如何工作的呢?它是否像实现在 cpp 中一样有效?

您不编译 .tpp.ipp-inl.h 等文件。它们就像头文件一样,只是它们只包含在其他头文件中。您只编译源 ( .cpp , .cc ) 文件。

原文由 Curious 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题