什么是相对path的好处,如“../include/header.h”的标题?

我已经回顾了问题如何正确使用include指令和C ++ #include语义,并没有解决这个问题 – 当我input标题的时候,也没有提出其他的build议…

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

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

与仅使用纯文件名相比:

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

或者可能是一个没有“ .. ”的相对名字:

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

我看到的问题是:

  • 您不能移动标题而不必担心哪些源文件包含它。
  • 你可以在依赖关系和错误报告中得到非常长的头文件path。 我今天有一个“ ../dir1/include/../../include/../dir2/../include/header.h ”。

我可以看到的唯一的优点是,虽然你不需要移动文件,但是你也许能够不用总是使用' -I '指令来查找标题,但是失去了灵活性,以及​​在sub子目录等似乎超过了好处。

那么,我忽略了一个好处?


感谢您的投入。 我认为共识是,我忽略使用“..”的符号没有什么大的好处。 一般来说,我喜欢“somewhere / header.h”符号; 我在新项目中使用它。 我正在工作的是一个新的东西。

其中一个问题是有各种各样的头文件集,通常带有诸如rspqr.hrsabc.hrsdef.hrsxyz.h 。 这些都与rsmp目录中的代码有关,但是其中一些头文件在rsmp而另一些头文件在中央include目录中,它们没有诸如rsmp类的rsmp 。 (对代码的其他各个领域重复一遍;在多个位置有头文件,需要随机的代码)。移动东西是一个主要的问题,因为这些年代代码变得如此复杂。 并且makefile中的-I选项是不一致的。 总而言之,几十年来这是一个不那么温和的忽视的悲惨故事。 解决这一切都没有打破任何东西将是一个漫长而乏味的工作。

我更喜欢path语法,因为它非常清楚头文件属于哪个名称空间或模块。

 #include "Physics/Solver.h" 

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

我几乎从来没有使用“..”的语法,但我有我的项目包括指定正确的基地点。

#include "../include/header.h"的问题是,它会经常意外地工作,然后一个看似不相关的变化会使它停止工作。

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

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

假设您正在使用包含-I. -I./lib的包含path运行编译器-I. -I./lib -I. -I./lib 。 怎么了?

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

此外,如果以后从#includepath中删除-I./lib ,则会破坏./lib/feature/feature.c

我发现像下面这样更好一些:

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

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

IANALL,但我不认为你应该把..的实际C或C ++源文件,因为这是不可移植的,标准不支持它。 这与在Windows上使用\相似。 只有在你的编译器不能使用任何其他方法的时候才行。

将源代码树看作嵌套命名空间,包含path允许您将目录拉入该命名空间的根目录。 然后问题是为您的代码库形成一个逻辑名称空间,而不pipe代码是如何在磁盘上组织的。

我会避免像这样的path:

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

就我个人而言,我倾向于像下面的path添加到我的项目包括path – "..;../..;../../..;../../../.."

这使您可以对#include应用一种隐藏规则,并允许在不破坏其他代码的情况下自由移动头文件。 当然,如果你不小心的话,这会导致绑定到错误的头文件的风险,因为非完全限定的名字可能(或随时间推移)不明确。

我倾向于完全限定公共标题中的#include ,所以任何第三方使用我的代码都不需要添加"..;../..;../../..;../../../.."到他们的项目 – 这只是我的私人代码和构build系统的便利。

因为那么你把文件放在项目的根目录下,当你把它检入到源代码控制中,而另外一个开发者把它检出到本地系统的不同位置时,事情还是有效的。

窗口上的相对path的另一个问题是MAX_PATH。 这将触发编译问题,例如交叉编译为Android和你的path长度大于260长。