对于标题,相对路径有什么好处,例如“../include/header.h”?

问题描述 投票:50回答:7

我已经回顾了问题How to use include directive correctlyC++ #include semantics并且都没有解决这个问题 - 当我输入标题时,SO也没有提出其他问题......

如果有的话,写作的好处是什么:

#include "../include/someheader.h"
#include "../otherdir/another.h"

与仅使用普通文件名相比:

#include "someheader.h"
#include "another.h"

或者没有'..'的相对名称:

#include "include/someheader.h"
#include "otherdir/another.h"

我看到的问题是:

  • 您无法移动标题而不必担心哪些源文件包含它。
  • 您最终可能会在依赖项和错误报告中使用非常长的标头路径。今天我有一个“../dir1/include/../../include/../dir2/../include/header.h”。

我能看到的唯一优点是,虽然你不需要移动文件,但是你可以在不使用'-I'指令来查找标题的情况下逃脱,但是失去灵活性,以及​​在子程序中编译的复杂性子目录等似乎超过了好处。

那么,我是否忽视了一项福利?


感谢您的投入。我认为大家一致认为,使用“......”的符号没有任何重大好处,我忽略了。一般来说,我喜欢“somewhere / header.h”符号;我确实在新项目中使用它。我正在努力的是新事物。

其中一个问题是有各种标题集,通常有一个前缀,如rspqr.hrsabc.hrsdef.hrsxyz.h。这些都与rsmp目录中的代码有关,但是有些标题位于rsmp中,而其他标题位于中央include目录中,其中没有rsmp等子目录。 (并重复代码的其他各个方面;在多个位置都有标题,需要其他位代码随机使用。)移动内容是一个主要问题,因为多年来代码变得如此复杂。并且makefile与提供-I选项不一致。总而言之,这是一个悲伤的故事,讲述了几十年来不那么温和的疏忽。在不破坏任何东西的情况下解决所有问题将是一项漫长而乏味的工作。

c include header
7个回答
36
投票

我更喜欢路径语法,因为它非常清楚头文件所属的命名空间或模块。

#include "Physics/Solver.h"

非常自描述而不需要每个模块将其名称作为头文件的前缀。

我几乎从不使用“..”语法,而是我的项目包括指定正确的基本位置。


24
投票

#include "../include/header.h"的问题在于它经常会偶然发生,然后一个看似无关的变化会让它在以后停止工作。

例如,请考虑以下源布局:

./include/header.h
./lib/library.c
./lib/feature/feature.c

让我们说你用-I. -I./lib的包含路径运行编译器。怎么了?

  • ./lib/library.c可以做#include "../include/header.h",这是有道理的。
  • ./lib/feature/feature.c也可以做#include "../include/header.h",即使它没有意义。这是因为编译器将尝试相对于当前文件的位置的#include指令,如果失败,它将尝试相对于#include路径中的每个-I条目的#include指令。

此外,如果你以后从-I./lib路径中删除#include,那么你打破./lib/feature/feature.c

我发现以下内容更可取:

./projectname/include/header.h
./projectname/lib/library.c
./projectname/lib/feature/feature.c

我不会添加除-I.之外的任何包含路径条目,然后library.cfeature.c都将使用#include "projectname/include/header.h"。假设“projectname”可能是唯一的,这在大多数情况下不会导致名称冲突或模糊。如果绝对必要,您还可以使用include路径和/或make的VPATH功能将项目的物理布局分割为多个目录(例如,为了适应特定于平台的自动生成的代码;当您使用#include "../../somefile.h"时,这确实会崩溃)。


9
投票

IANALL,但我不认为你应该把..放在实际的C或C ++源文件中,因为那不是便携式的,而且标准不支持它。这类似于在Windows上使用\。只有在编译器无法使用任何其他方法时才能执行此操作。


2
投票

将源树视为嵌套命名空间,包含路径允许您将目录拉入此命名空间的根目录。问题是如何为代码库形成逻辑命名空间,而不管代码在磁盘上的组织方式。

我会避免像这样的路径:

  • "include/foo/bar.h" - “包括”似乎不合逻辑和多余
  • "../foo/bar.h" - “..”假定相对位置并且是脆弱的
  • "bar.h" - 除非bar.h在当前目录中,否则会污染全局命名空间并要求模糊。

就个人而言,我倾向于在我的项目中添加如下路径包括路径 - "..;../..;../../..;../../../.."

这允许您对#includes应用一种隐藏规则,并允许在不破坏其他代码的情况下自由移动标题。当然,这是以引入绑定到错误的头文件的风险为代价的,如果您不小心,因为非完全限定的名称可能(或变得时间)不明确。

我倾向于在公共标题中完全限定#includes,因此任何使用我的代码的第三方都不需要将"..;../..;../../..;../../../.."添加到他们的项目中 - 这只是我的私有代码和构建系统的便利。


1
投票

因为那时你把文件放在项目的根目录下,当你把它检查到源代码控制中,而另一个开发人员将它检查到本地系统的不同位置时,事情仍然有效。


1
投票

具有相对路径的Windows上的另一个问题是MAX_PATH。这将触发编译问题,例如交叉编译为Android和你的路径长度超过260。


1
投票

在以下情况下,使用一个或多个“#include ""”序列开始../指令的路径:

  • 您想要包含与包含文件的搭配固定的文件
  • 您正在构建POSIX系统或VC ++和
  • 你希望避免含糊不清的文件。

提供代码库包含错误的位置以及随后导致难以诊断的故障的示例总是很容易的。但是,即使您的项目没有故障,如果依靠绝对路径指定相对于彼此的文件,它也可能被第三方滥用。

例如,考虑以下项目布局:

./your_lib/include/foo/header1.h
./your_lib/include/bar/header2.h
./their_lib/include/bar/header2.h

your_lib / include / foo / header1.h应该如何包含your_lib / include / bar / header2.h?我们考虑两个选择:

  1. #include <bar/header2.h> 假设your_lib / include和their_lib / include都被引用为标题​​搜索路径(例如,使用GCC的-I-isystem选项),那么选择哪个header2.h对搜索这两个路径的顺序很敏感。
  2. #include "../bar/header2.h" 编译器将搜索的第一个位置是your_lib / include / foo / header1.h的位置,即your_lib / include / foo /。它将首先尝试your_lib / include / foo /../ bar / header2.h,它将减少到your_lib / include / bar / header2.h,它将找到正确的文件。标题搜索路径根本不会被使用,并且几乎没有模糊性的空间。

在这种情况下,我强烈建议选择2)。

回答其他答案中的一些论点:

  • @ andrew-grant says: ...它清楚地表明了头文件所属的命名空间或模块。 也许。但相对路径可以解释为“在同一模块中”。它们在不同模块中存在多个具有相同名称的目录的情况下提供了清晰度。
  • @ bk1e says: ......它经常会偶然发生...... 我认为相对路径只会在非常罕见的情况下偶然发生,因为项目从一开始就被打破并且很容易修复。在不引起编译错误的情况下遇到这样的名称冲突似乎不太可能。一种常见的情况是,依赖项目的文件包含一个标题,其中包含另一个标题。编译测试套件时,如果与该依赖项目隔离编译,则会导致“无此类文件或目录”错误。
  • @singlenegationelimination says ......这不便携,标准不支持它。 ISO C标准可能未指定编译或运行程序的系统的所有详细信息。这并不意味着它们不受支持,只是标准没有过度指定C将运行的平台。 (在POSIX标准中,如何在常见的现代系统""上解释<>likely originates之间的区别。)
  • @ daniel-paull says “......”假定相对位置且易碎 脆弱怎么样?大概是对两个文件的搭配敏感。因此,当包含文件的作者控制其位置时,应该(并且始终)使用“..”。
© www.soinside.com 2019 - 2024. All rights reserved.