我正在读“绝对C ++第五版”一书。 在页716中, 我真的不明白它为什么需要包括“pfarray.cpp”
包含“pfarray.h”还不够吗?
更具体地说,即使我们在.h文件中有声明但在.cpp文件中有实现,当我们仍然必须包含.cpp文件时?
提前谢谢。
答案 0 :(得分:5)
当您编写#include anything.any_extension
时,扩展程序对预处理程序并不重要。它真的像一个"从该文件中获取内容并将其粘贴到此文件" 类型的暴力机制中。因此,如果内部代码是合法的,您可以包含任何没有错误的内容,并且您可以使用任何扩展名来命名头文件。所以你甚至可以使用.txt
扩展名来命名它们对预处理器来说并不重要。
我建议包含源文件的做法相当混乱,主要是从构建的角度来看,因为它不是很清楚源文件(cpp,cc等)是否应该作为一个单独构建要链接的对象文件或#included或两者。
然而,它有时会完成。例如,pfarray.cpp
可能包含模板的实现,因为模板通常需要在生成代码的站点的编译时可见其完整实现,有时作者建立#including包含源文件扩展名的文件的习惯,以避免放置将实现详细信息放入同一个头文件中,同时统一符合有利于将所有此类详细信息放入以源文件约定命名的文件中的样式。
可以做到这一点的另一个原因,但我不认为它是在你的情况下完成它的原因,是作为构建优化(参见Unity构建)。编译和链接较少的文件有时会更有效,因此对源文件使用#include
可能是将它们融合到一个构建目标中的粗略方法。
答案 1 :(得分:5)
你不必。
翻译单元是一组包含定义和声明的文件。编译翻译单元时,编译器需要知道有关声明的所有内容并反复重新解析它们。另一方面,这些定义只能编译一次,并重新用于其他单位。
翻译单元可以分为.h
和.cpp
个文件。您应该将.h
中的声明和.cpp
文件中的定义放在一个定义规则中。这种方法也减少了编译时间。
编写模板-d类和函数(没有专门化),一些编码器(我认为是一个坏习惯)会将实现放在.cpp
文件中,并且必须将它们包含在相应的.h
的末尾。 {1}}文件或需要它们的.cpp
文件。这只是令人困惑。更好的命名约定是将这些类型的.cpp
文件重命名为.impl.cpp
,并将其包含在.h
文件的末尾。