首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在实现标头中定义的模板函数和类时使用"tpp“文件?

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

Stack Overflow用户
提问于 2017-06-27 06:59:16
回答 4查看 27.4K关注 0票数 33

请参阅this question about implementing templates.中的第一个答案

具体来说,请注意这句话。

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

我大胆地说出了我最感兴趣的部分。

.tpp文件的意义是什么?我试着做了那一页中建议的事情,结果成功了。但后来,我将文件扩展名更改为任意胡言乱语(比如.zz或.ypp),它仍然有效!它应该有效吗?如果它是.tpp或任何其他扩展,有什么关系吗?为什么不使用.cpp呢?

还有一件事我很困惑。

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

但是,如果我有一个定义模板函数的标头,并且我的实现在一个文件中,并且具有一个随机的奇怪的扩展名,那么它是如何编译的呢?而且,每次我编译#include的任何源代码时,是否都会编译这些实现呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-06-27 07:01:17

如果它是.tpp或任何其他扩展,有什么关系吗?为什么不使用.cpp呢?

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

.tpp文件的意义是什么?

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

Something.hpp

代码语言:javascript
运行
复制
#pragma once

namespace space {

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

} // namespace space

#include "Something.ipp"

Something.ipp

代码语言:javascript
运行
复制
#pragma once

namespace space {

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

} // namespace space

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

不能将通用模板代码拆分为实现文件。您需要完整的可见代码才能使用模板,这就是为什么您需要将所有内容都放在头文件中。有关更多信息,请参见Why can templates only be implemented in the header file?

但是如果实现文件有一些看起来很奇怪的文件扩展名,那么从编译的角度来看,它是如何工作的呢?它是否与cpp中的实现一样有效?

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

票数 37
EN

Stack Overflow用户

发布于 2017-06-27 07:01:36

对预处理程序来说,文件扩展名是没有意义的;.h也没有什么神圣之处。这只是惯例,所以其他程序员知道并理解文件中包含的内容。

预处理器将允许您将任何文件包含到任何翻译单元(这是一个非常钝的工具)。像这样的扩展只会帮助澄清应该包含在哪里的内容。

票数 7
EN

Stack Overflow用户

发布于 2017-06-27 07:02:29

如果它是.tpp或任何其他扩展,有什么关系吗?为什么不使用.cpp呢?

实际使用哪个扩展并不重要,只要它与用于C++翻译单元的任何标准扩展不同。

其理由是具有不同的文件扩展名,因为任何用于翻译单元的C++构建系统(.cpp.cc、.)通常都会检测到它们。因为将这些文件转换为源文件将失败。它们必须是包含模板声明的相应头文件的#included。

但是如果实现文件有一些看起来很奇怪的文件扩展名,那么从编译的角度来看,它是如何工作的呢?

它需要像前面提到的那样被编译为#included。

它是否与cpp中的实现一样有效?

嗯,对于编译时间,没有像从翻译单元生成的纯对象文件那样有100%的效率。当包含#include语句的头部发生变化时,将再次编译它。

而且,每次我编译#include的任何源代码时,是否都会编译这些实现呢?

是的,他们是。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44774036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档