什么是相对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.h
, rsabc.h
, rsdef.h
和rsxyz.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
指令,如果失败,它将尝试相对于#include
path中的每个-I
条目的#include
指令。
此外,如果以后从#include
path中删除-I./lib
,则会破坏./lib/feature/feature.c
。
我发现像下面这样更好一些:
./projectname/include/header.h ./projectname/lib/library.c ./projectname/lib/feature/feature.c
我不会添加-I.
以外的任何包含path条目-I.
,然后library.c
和feature.c
都会使用#include "projectname/include/header.h"
。 假设“项目名称”可能是唯一的,在大多数情况下,这不应该导致名称冲突或含糊不清。 您也可以使用includepath和/或make的VPATH
function将项目的物理布局拆分到多个目录(如果绝对必要的话)(例如,为了适应特定于平台的自动生成的代码;当您使用#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长。