C++ 为什么要将标题放在单独的目录中?
我知道,在C/C++项目中,将头文件放在一个目录(如C++ 为什么要将标题放在单独的目录中?,c++,c,directory-structure,C++,C,Directory Structure,我知道,在C/C++项目中,将头文件放在一个目录(如include)中,并将实现放在一个单独的目录(如src)中是很常见的。我一直在玩弄不同的项目结构,我想知道这是否有客观的原因,或者它只是一种惯例?它让你的文件夹结构更干净。头文件和源文件明显不同,用于不同的用途,因此将它们分开是有意义的。从这个角度来看,问题基本上与“为什么源文件和文档放在不同的文件夹中”相同?计算机对你在文件夹中放什么和不放什么高度不可知,文件夹在很大程度上只是一个方便的抽象,因为我们人类解析、存储和调用信息的方式 还有一个
include
)中,并将实现放在一个单独的目录(如src
)中是很常见的。我一直在玩弄不同的项目结构,我想知道这是否有客观的原因,或者它只是一种惯例?它让你的文件夹结构更干净。头文件和源文件明显不同,用于不同的用途,因此将它们分开是有意义的。从这个角度来看,问题基本上与“为什么源文件和文档放在不同的文件夹中”相同?计算机对你在文件夹中放什么和不放什么高度不可知,文件夹在很大程度上只是一个方便的抽象,因为我们人类解析、存储和调用信息的方式
还有一个事实是头文件仍然有用,即使在您构建了,即如果您正在构建库,而有人想要使用该库,他们需要的是头文件——而不是源文件——因此将这些头文件捆绑在一起——在
bin
和include
中获取内容,而不必筛选src
——要容易得多。惯例是原因之一——大多数情况下,通过有效的抽象,您只关心接口,只需查看标题即可轻松实现
但这不是唯一的原因。如果您的项目是按模块组织的,那么您很可能需要在不同的模块中包含一些标题,并且希望您的include目录中没有其他“噪音”文件
此外,如果您计划重新分发模块,您可能希望隐藏实现细节。因此,您只提供头文件和二进制文件,而从一个文件夹中分发头文件,而不在其中包含任何其他文件,这更简单
还有一个我实际上更喜欢的替代方案——公共头放在一个单独的文件夹中(这些文件夹包含最小的接口-没有任何实现细节可见),私有头和实现文件是单独的(可能,但不一定,在单独的文件夹中)。此外(有争议?)对于保持事物有序、对其他项目有用等等,有一个非常中立和客观的优势:编译时间
特别是,在一个包含大量文件的大型项目中,这取决于标题的搜索路径(.c/.cpp文件使用
#包括“headername.h”
,而不是#include”。/../gfx/misc/something/headername.h“
,并且编译器传递了正确的参数以实现这一点)您大大减少了编译器在搜索正确标题时需要扫描的条目数。由于大多数编译器分别为每个编译的文件启动,因此它们需要读入include路径上的文件列表,并为每个编译的文件寻找正确的头。如果include路径上有一堆.c、.o和其他不相关的文件,则查找其中的include会相应地花费更长的时间。简而言之,有几个原因:
- 可维护代码
- 代码设计良好且整洁
- 更快的编译时间(有时,对于较小的更改)
- 更容易分离文档等接口
- 可以避免编译时的循环依赖
- 容易复习
看看这篇文章,它解释得很好。我更喜欢把它们放在同一个目录中。原因: 接口规范文件和实现该接口的源文件属于项目的同一部分。假设您有
子系统x
。然后,如果将subsystemx
文件放在subsystemx
目录中,subsystemmx
是自包含的
如果有很多include文件,当然你可以做subsystemx/include
和subsystemx/source
,但是我认为如果你把class Foo
的定义放在Foo.hpp
和Foo.cpp
中,你肯定想看到这两个文件(或者至少可以很容易地做到这一点)一起放在一个目录列表中。查找与foo相关的所有文件
ls foo*
查找所有实现文件:
ls *.cpp
ls *.hpp
查找所有声明文件:
ls *.cpp
ls *.hpp
简单明了。这也许可以解释一下:或者可能是这样:我曾经有三个数学库项目的位置:src/for.c、include/for internal.h和api/for the.h,用于外部使用,用于使用库的应用程序。我甚至试着通过将它们命名为.API来区分面向公众的API头,但这混淆了工具链。这是用于c
,但可能会有所帮助:你能解释一下这种分离是如何降低循环依赖的风险的吗?我很确定@parasrish回答了一个不同的问题“为什么要将头分离到单独的文件中?”但子系统之外的代码需要使用公共接口,因此公共接口头需要简单且可控地访问。如果您必须猜测子系统X的哪些头文件仅供内部使用,哪些头文件供外部使用,以及哪些头文件定义了API,那么您能想象这样的混乱吗?私有头可以与源代码共存,这没有问题。但是消费者需要的公共标题——这些标题需要以一种更受控制的方式提供。@JonathanLeffler我设计的是这样就没有私有标题了。包含“subsystemx/foo.hpp”
总是有意义的。如果有内部细节,我会将它们隐藏在实现文件中。另外,您如何确定头文件仅供私人使用?您很幸运能够在这样小的系统上工作。@JonathanLeffler如果您需要私人头文件,请在文件名中添加后缀\u internal
。我同意这种方法。也有