[英]Including header files style - C++
我有一个具有以下目录结构的项目。
root
--include
----module1
----module2
--src
----module1
----module2
所以一个文件说src/module1
foo.cpp
中的foo.cpp
必须包括像,
#include "../../include/module1/foo.hpp"
这看起来很混乱,很难写。 我发现写作包括喜欢
#include <module1/foo.h>
并且在编译看起来很整洁时提供包含文件搜索路径到root/include
。 但是,我不确定这种风格有任何缺点。
您更喜欢哪一个?为什么? 你也看到以上述方式组织文件有什么问题吗?
#include "../../include/module1/foo.hpp"
应尽可能避免指定路径。 编译器为您提供了更清晰的替代方案。 此外,干净的设计应该确保您不需要处理包含标题的相对路径。
可以从标准中更好地了解使用哪一个(包括使用引号还是尖括号)。
从我的C ++草案副本:
16.2源文件包含
2表单的预处理指令
#include <h-char-sequence> new-line`
搜索一系列实现定义的位置,以查找由
<
和>
分隔符之间的指定序列唯一标识的标头,并使标头的整个内容替换该指令。 如何指定场所或标识的头是实现定义的。3表单的预处理指令
# include "q-char-sequence" new-line
导致由“delimiters”之间的指定序列标识的源文件的全部内容替换该指令。以实现定义的方式搜索指定的源文件。如果不支持此搜索,或者搜索失败,该指令被重新处理,就像它读取一样
#include <h-char-sequence> new-line`
使用原始指令中相同的包含序列(包括>字符,如果有的话)。
7虽然实现可以提供一种机制来使任意源文件可用于<>搜索,但一般来说程序员应该使用<>表单作为实现提供的头文件,并使用“”表单来实现控制之外的源。
我支持两种风格......用于不同的用途
我们假设您的示例中还有一个目录root/src/common
// in src/module1/foo.cpp
#include "module1/foo.h"
#include "../common/stringProcessing.h"
包括
我不喜欢看到'include'目录,因为当然说找到确切的头文件更难...但是当你开始并转向多个独立库时你需要抽象,因为你希望能够在不改变代码的情况下移动各种组件,我都是为了保持一致性。
此外,使用'..'总是存在风险,因为向后遍历的符号链接,它不会出现在你想到的地方:/
资源
有时您的标头不是公共的,因此不在include
目录中。 这些通常用于与您的客户无关的实施细节。 对于那些我使用..
如果需要和精确的确切位置。
这允许: - 不要将-I
与src
所有可能目录src
- 在源代码中轻松找到文件 - 轻松测试源代码之间的依赖关系(grep for ..
)
杂项
如果我要打字
#include "module/foo.h"
然后我希望使用:
module::Foo myClass;
这使得将一种特定类型与一个特定模块匹配变得容易。
要求一个库 - 一个名称相同的命名空间,可以很容易地导航我们工作的一些~300或~400个组件:我们需要通过某种方式来组织它们!
这意味着您的初始布局会被重新设计为(对于module
项目):
root
-- include
---- module
------ part1
------ part2
-- src
---- part1
---- part2
然后使用以下指令: -I/path../root/include
我希望您创建libmodule.so
库或module
二进制文件。
我更喜欢第二种方式
#include <module1/foo.h>
我发现它使源更易于查看。 问题是,当其他人来看你的代码时,它不一定是头文件所在的固有位置,而包含的第一种方式是。
每种风格都有一些缺点,但我更喜欢你指定的风格。 包含路径不得包含任何向上相关性(例如../..
),并且必须指定它所依赖的模块。
作为一个小改进,我建议你允许module1中的cc
文件直接访问他们的.h
文件:
module1/%.cc: -I $ROOT/includes/module1
或类似的。 这将在您的c文件中创建一个视觉效果,区分外部包含和默认包括:
// module1/abc.cc
#include <abc.h>
#include <module2/def.h>
Google的C ++风格指南中有一节介绍了包含的排序和命名。 它基本上同意到目前为止在其他答案中所说的内容,但值得一看,因为它非常具体。
我更喜欢(和Google同意)在include指令中没有使用..的相对路径。 您初步评估它看起来整洁是正确的。 拥有冗长,笨重的相对路径会使事情更难阅读,更难以重构。 我认为你的方法是正确的。
至于将源文件和包含文件分成两个不同的子树:为什么不将源头文件放在源文件旁边? 它使它们更容易匹配。 除非你希望其他项目使用你的标题,只是链接到你的二进制文件,我想。
<耸肩/>
我不在#include
指令中使用路径。 根据我的经验,它们总是在维护阶段引起问题。 许多编译器允许您为头文件指定搜索树。
他们会的。 您的层次结构将会改变 您可能希望将文件放在不同的驱动器上。 当其他用户修改您的代码时,他们可能会更改位置。 当文件移植到另一个项目时,文件可能会移动。 没有什么能阻止您的文件移动。
知道文件将移动,如果路径在文件中,则移动文件时必须修改该文件。 如果没有文件中的路径,则只需要更改构建指令。 对于大型项目,修改许多文件很麻烦(即使使用脚本)。
在我看来, #include
指令中的路径是邪恶的。 执行此操作的人员应接受再培训或发送给其他公司。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.