我有一个具有以下目录结构的项目。
root
--include
----module1
----module2
--src
----module1
----module2
因此foo.cpp
中的文件src/module1
必须包含类似
#include "../../include/module1/foo.hpp"
这看起来很乱,而且很难写。我发现写作包括像
#include <module1/foo.h>
并在编译看起来整洁时向root/include
提供包含文件搜索路径。但是,我不确定这种风格有任何缺点。
您更喜欢哪一个?为什么?你也看到以上述方式组织文件有什么问题吗?
答案 0 :(得分:4)
#include "../../include/module1/foo.hpp"
应尽可能避免指定路径。编译器为您提供了更清晰的替代方案。此外,干净的设计应该确保您不需要处理包含标题的相对路径。
更好地了解使用哪一个(包括使用引号还是尖括号) 可以从标准。
从我的C ++草案副本:
16.2源文件包含
2
形式的预处理指令
#include <h-char-sequence> new-line`
搜索序列 实现定义的地方 标题由唯一标识
<
和>
之间的指定序列 分隔符,并导致替换 该指令的全部内容 标题的内容。怎么样的地方 指定或标识标题 是实现定义的。3 A 表格的预处理指令
# include "q-char-sequence" new-line
导致替换它 指令由整个内容组成 由...标识的源文件 指定序列之间的“ 分隔符。 搜索指定的源文件 以实现定义的方式。 如果不支持此搜索,或者如果 搜索失败,指令是 重新处理就像读了
#include <h-char-sequence> new-line`
具有相同的包含序列 (包括&gt;字符,如果有的话)来自 原始指令。
7 虽然实现可能会提供制作机制 可用的任意源文件 &lt; &GT;搜索,一般程序员 应该使用&lt; &GT;标题的形式 提供实施,和 外部来源的“”形式 控制实施。
答案 1 :(得分:2)
我支持两种风格......用于不同的用途
假设您还有一个目录root/src/common
用于我的示例
// in src/module1/foo.cpp
#include "module1/foo.h"
#include "../common/stringProcessing.h"
包含强>
我不想看到'include'目录,因为当然说找到确切的头文件更难...但是当你开始并向多个独立库移动时你需要抽象,因为你想要能够在不改变代码的情况下移动各种组件,而且我都是为了保持一致性。
此外,使用'..'总是存在风险,因为向后遍历的符号链接,它不会出现在你想到的地方:/
<强>来源
有时您的标头不公开,因此不在include
目录中。这些通常用于与您的客户无关的实施细节。对于那些我使用..
的人,如果需要,请准确确切地说明。
这允许:
- 不要将-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
二进制文件。
答案 2 :(得分:1)
我更喜欢第二种方式
#include <module1/foo.h>
我发现它使源更易于查看。问题是,当其他人来看你的代码时,它不一定是头文件所在的固有位置,而包含的第一种方式是。
答案 3 :(得分:1)
每种风格都有一些缺点,但我更喜欢你指定的风格。包含路径不得包含任何向上相关性(例如../..
),并且必须指定它所依赖的模块。
答案 4 :(得分:1)
作为一个小改进,我建议您允许module1中的cc
个文件直接访问他们的.h
文件:
module1/%.cc: -I $ROOT/includes/module1
或类似的。这将在您的c文件中创建一个视觉效果,区分外部包含和默认包括:
// module1/abc.cc
#include <abc.h>
#include <module2/def.h>
答案 5 :(得分:1)
谷歌的C ++风格指南有一个section,他们讨论了包含的排序和命名。它基本上同意到目前为止在其他答案中所说的内容,但值得一看,因为它非常具体。
我更喜欢(并且Google同意)在include指令中没有使用..的相对路径。您初步评估它看起来整洁是正确的。拥有冗长,笨重的相对路径会使事情更难阅读,更难以重构。我认为你的方法是正确的。
至于将源文件和包含文件分成两个不同的子树:为什么不将源头文件放在源文件旁边?它使它们更容易匹配。除非你希望其他项目使用你的标题,只是链接到你的二进制文件,我想 &LT;耸肩/&GT;
答案 6 :(得分:1)
我不在#include
指令中使用路径。根据我的经验,它们总是在维护阶段引起问题。许多编译器允许您为头文件指定搜索树。
他们会的。您的层次结构将会改变您可能希望将文件放在不同的驱动器上。当其他用户修改您的代码时,他们可能会更改位置。当文件移植到另一个项目时,文件可能会移动。没有什么能阻止您的文件移动。
知道文件将移动,如果路径在文件中,则移动文件时必须修改文件。如果没有文件中的路径,则只需要更改构建指令。对于大型项目,修改许多文件很麻烦(即使使用脚本)。
在我看来,#include
指令中的路径是邪恶的。执行此操作的人员应接受再培训或发送给其他公司。