为啥我们不在“.cpp.h”文件中编译模板实现?
Posted
技术标签:
【中文标题】为啥我们不在“.cpp.h”文件中编译模板实现?【英文标题】:Why do we not compile template implementation in a ".cpp.h" file?为什么我们不在“.cpp.h”文件中编译模板实现? 【发布时间】:2016-05-15 21:28:49 【问题描述】:在制作模板链表时,我们创建 list.h 和 list.cpp.h,而不是文件 list.h 和 list.cpp。 .cpp.h 文件包含链表类的实现。在 list.h 的末尾,在 #ENDIF 之前,我们 #include "list.cpp.h"。
我知道通过将 .cpp 文件作为头文件,我们可以避免编译它,但是这是如何工作的呢?过去我们需要编译依赖于使用“template
编辑:我的问题被标记为重复,带有指向 Why can templates only be implemented in the header file? 的链接,我已经阅读过。这个问题没有回答为什么不需要像普通的 .cpp 实现文件那样编译模板实现。如果我们可以通过制作头文件来避免编译实现,为什么我们不对每个实现都这样做呢?有什么缺点?
实例化模板是否会编译该模板的每个实例的代码?如果我的 .cpp 曾经需要在其功能之一中使用模板,那么如果它避免了初始编译,我为什么不将其更改为头文件呢?
我希望我的问题更有意义。
【问题讨论】:
“我知道通过将 .cpp 文件作为头文件,我们可以避免编译它,” => 头文件被编译,只是 按照惯例 将内容放入.h
文件时,您只会将可以安全地多次包含在项目中的内容放入其中。如果您将int foo;
放入头文件,然后将#include
该文件放入多个源文件中,您将在链接器时收到关于foo
的多个声明的错误。模板是可以安全包含多次的类别中的东西......比如内联函数定义,它们按照链接所述进入标题。
我不清楚你在问什么。当执行#include "file.h"
的翻译单元被编译时,.h
文件中的代码被编译,因为#include
是一个简单的文本替换。当您说“为什么我们不对每个实现都这样做?”时,您的确切意思是什么。您确实将每个模板实现放在头文件中(如果它需要对多个单元可见)
【参考方案1】:
请记住,#include
指令只是将标头的内容拉入当前正在编译的文件中。所以模板确实被编译了;它在#include
s 定义模板的文件的每个翻译单元中编译。当使用模板时(稍后在该文件中),它会被实例化。
【讨论】:
【参考方案2】:正如您所说,您正在将模板作为头文件包含在内,因为您的 .h 文件最后包含 .ccp.h 文件。
所以这是您项目的惯例,将 normal .h 和模板代码分隔在两个文件中。
因此,在您的情况下,模板代码被编译成常规的 .cpp 代码。
您想要避免这种情况的原因是“膨胀”——每个 .cpp 文件都会创建它自己的该 cpp 单元中使用的模板代码的副本,所以如果 A.cpp 和 B.cpp 都包含T.cpp.h,如果他们使用相同的模板,他们可能会创建相同的代码,并且需要一个智能优化器来删除所有重复。
【讨论】:
以上是关于为啥我们不在“.cpp.h”文件中编译模板实现?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Yarn 不在 .bin 文件夹中安装所有可执行文件?
当项目名称带有连字符时,为啥 VS 2010 ATL 简单对象向导不会生成 .cpp/.h 文件?
为啥将class反编译为java后,java直接编译时有错误