Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么要使用“a”;tpp“;实现头中定义的模板化函数和类时的文件?_C++_Templates - Fatal编程技术网

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

C++ 为什么要使用“a”;tpp“;实现头中定义的模板化函数和类时的文件?,c++,templates,C++,Templates,请参阅第页的第一个答案 具体来说,请注意这一引文 一种常见的解决方案是将模板声明写入头文件,然后在实现文件(例如.tpp)中实现该类,并将该实现文件包含在头文件的末尾 我把我最感兴趣的部分加粗。 .tpp文件的意义是什么?我试着完全按照那页上的建议去做,结果成功了。但后来,我把文件扩展名改成了任何随机乱码(比如.zz或.ypp),它仍然有效!它应该有用吗?tpp或任何其他扩展是否重要?为什么不使用.cpp呢 还有一件事我很困惑。 如果我的实现是用.cpp和头定义的非模板函数编写的,那么我只需要编

请参阅第页的第一个答案

具体来说,请注意这一引文

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

我把我最感兴趣的部分加粗。
.tpp文件的意义是什么?我试着完全按照那页上的建议去做,结果成功了。但后来,我把文件扩展名改成了任何随机乱码(比如.zz或.ypp),它仍然有效!它应该有用吗?tpp或任何其他扩展是否重要?为什么不使用.cpp呢

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

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

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

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

.tpp文件的意义是什么

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

Something.hpp

#pragma once

namespace space {

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

} // namespace space

#include "Something.ipp"
#pragma once

namespace space {

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

} // namespace space
#pragma一次
命名空间空间{
模板
分类{
公众:
取消某些_接口();
};
}//命名空间空间
#包括“Something.ipp”
Something.ipp

#pragma once

namespace space {

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

} // namespace space

#include "Something.ipp"
#pragma once

namespace space {

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

} // namespace space
#pragma一次
命名空间空间{
模板
void Something::some_interface(){
//实施
}
}//命名空间空间

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

不能将常规模板代码拆分为实现文件。为了使用模板,您需要看到完整的代码,这就是为什么您需要将所有内容都放在头文件中。欲了解更多信息,请参阅

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


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

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

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

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

<> p>实际上扩展了什么,没有什么关系,只要它与C++翻译单元中使用的任何标准扩展不同。 推理是有一个不同的文件扩展名,因为它们通常由任何C++编译系统检测到翻译单元(<代码> .CPP < /COD>,<代码> .cc,…)。因为将这些文件转换为源文件将失败。它们必须由包含模板声明的相应头文件进行
#include
d

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

它需要
#包括
d才能按上述方式编译

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

好吧,在编译时间方面并不像从翻译单元生成的纯对象文件那样有100%的效率。一旦包含
#include
语句的标题发生更改,它将再次编译

每次我编译任何源代码时都会编译实现吗


<>是,

文件头文件扩展在C++中不重要,即使标准源文件扩展名如>CPP >应避免。

然而,有既定的惯例。这些帮助人类程序员浏览代码。调用模板实现文件
.tpp
就是这样的约定之一

还没有人提到的一点是,一些外部工具可能依赖于这样的约定


例如,我经常使用一个流行的
grep
替代品,它只允许搜索给定类型的文件。这个程序将识别<代码> .tpp < /Case>文件,作为C++,但不能,例如,<代码> .Z.文件

,所以,要确保我在遵循,编写诸如<代码>的东西包括“A.tpp”。在头文件中,其中
A.tpp
是带有头文件实现的文件,这相当于简单地将实现写入头文件本身?@Manuel完全相同,它本质上是将该文件复制粘贴到当前文件中