8

我有一个具有以下目录结构的项目。

root
--include
----module1
----module2
--src
----module1
----module2

所以说的文件foo.cpp必须src/module1包括,

#include "../../include/module1/foo.hpp"

这看起来很乱,很难写。我发现写作包括喜欢

#include <module1/foo.h>

root/include并在编译时提供包含文件搜索路径,看起来很整洁。但是,我不确定这种风格有什么缺点。

你更喜欢哪一个,为什么?您还发现以上述方式组织文件有什么问题吗?

4

7 回答 7

4
#include "../../include/module1/foo.hpp"

应尽可能避免指定路径。编译器为您提供了一个更清洁的替代方案来实现相同的目标。此外,干净的设计应该确保您不需要为包含标题而调整相对路径。

可以从标准中更好地了解使用哪个(包括是否使用引号或尖括号)。

从我的 C++ 草案副本中:

16.2 源文件包含

2形式的预处理指令

#include <h-char-sequence> new-line`

在一系列实现定义的位置中搜索由<> 分隔符之间的指定序列唯一标识的标头,并用标头的全部内容替换该指令。如何指定位置或标识的标头是实现定义的。

3形式的预处理指令

# include "q-char-sequence" new-line 

导致将该指令替换为由 " 分隔符之间的指定序列标识的源文件的全部内容。以实现定义的方式搜索命名的源文件。如果不支持此搜索,或者搜索失败, 该指令被重新处理,就好像它读取

#include <h-char-sequence> new-line`

具有与原始指令相同的包含序列(包括 > 字符,如果有的话)。

7尽管实现可以提供一种机制,使任意源文件可用于< > 搜索,但通常程序员应使用< > 形式作为实现提供的标题,而“”形式用于实现控制之外的源。

于 2010-01-28T17:07:06.433 回答
2

我支持这两种风格......用于不同的用途

假设您还有一个root/src/common用于我的示例的目录

// in src/module1/foo.cpp
#include "module1/foo.h"

#include "../common/stringProcessing.h"

包括

我不希望看到“包含”目录,因为当然要找到确切的头文件会更加困难......但是当您开始并转向多个独立库时,您需要抽象,因为您希望能够在不改变代码的情况下移动各种组件,我完全支持一致性。

此外,使用“..”总是存在风险,因为符号链接向后遍历,它不会去你想的地方:/

来源

有时您有不公开的标题,因此不在include目录中。这些通常用于与您的客户无关的实施细节。对于那些我使用..if need be 和精确位置的人。

这允许: - 不会将-I所有可能的目录弄乱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二进制文件。

于 2010-01-28T17:29:38.890 回答
1

我更喜欢第二种方式

#include <module1/foo.h>

我发现它使源代码更容易查看。问题是,当其他人来查看您的代码时,它不一定是头文件所在的固有位置,而包含的第一种方式是。

于 2010-01-28T17:04:45.890 回答
1

每种风格都有一些缺点,但我更喜欢你指定的那种。包含路径不能包含任何向上的相对性(例如../..),并且必须指定它所依赖的模块。

于 2010-01-28T17:06:01.143 回答
1

作为一个小改进,我建议您允许ccmodule1 中的.h文件直接访问它们的文件:

module1/%.cc: -I $ROOT/includes/module1

或类似的。这将在您的 c 文件中创建一个视觉效果,将外部包含与默认包含区分开来:

// module1/abc.cc
#include <abc.h>
#include <module2/def.h>
于 2010-01-28T17:18:03.923 回答
1

谷歌的 C++ 风格指南有一个关于这方面的部分,他们讨论了包含的排序和命名。到目前为止,它基本上与其他答案中所说的一致,但值得一看,因为它非常具体。

我更喜欢(并且 Google 同意)在包含指令中不使用 .. 的相对路径。您对它看起来整洁的初步评估是正确的。拥有长而笨重的相对路径会使事情更难阅读,也更难重构。我认为你的方法是正确的。

至于将源文件和包含文件分成两个不同的子树:为什么不将标头放在源文件旁边?它使匹配它们变得更容易。除非您希望其他项目使用您的标头并仅链接到您的二进制文件,否则我猜。
<耸肩/>

于 2010-01-28T17:18:54.007 回答
1

我不在#include指令中使用路径。以我的经验,它们总是在维护阶段引起问题。许多编译器允许您为头文件指定搜索树。

文件可以移动

他们会的。你的层次结构会改变。您可能希望将文件放在不同的驱动器上。当其他用户修改您的代码时,他们可能会更改位置。当它们被移植到另一个项目时,这些文件可能会移动。没有什么可以阻止您的文件移动。

移动文件而不修改它们

知道文件会移动,如果路径在文件中,移动时必须修改文件。没有文件中的路径,只需要更改构建指令。对于大型项目,修改许多文件是一件痛苦的事(即使是脚本)。

在我看来,#include指令中的路径是邪恶的。这样做的人应该接受再培训或被派往其他公司。

于 2010-01-28T18:33:01.777 回答