C++ #include 语义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/179213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:28:42  来源:igfitidea点击:

C++ #include semantics

c++c-preprocessor

提问by paercebal

This is a multiple question for the same pre-processing instruction.

这是同一预处理指令的多个问题。

1 - <> or "" ?

1 - <> 还是 "" ?

Apart from the info found in the MSDN:

除了在 MSDN 中找到的信息:

#include Directive (C-C++)

#include 指令 (C-C++)

1.a: What are the differences between the two notations?
1.b: Do all compilers implement them the same way?
1.c: When would you use the <>, and when would you use the "" (i.e. what are the criteria you would use to use one or the other for a header include)?

1.a:这两种符号有什么区别?
1.b:所有编译器都以相同的方式实现它们吗?
1.c:什么时候使用<>,什么时候使用“”(即,您将使用一个或另一个作为标题包含的标准是什么)?

2 - #include {TheProject/TheHeader.hpp} or {TheHeader.hpp} ?

2 - #include {TheProject/TheHeader.hpp} 或 {TheHeader.hpp} ?

I've seen at least two ways of writing includes of one's project headers. Considering that you have at least 4 types of headers, that is:

我已经看到至少有两种写法包含一个人的项目标题。考虑到您至少有 4 种类型的标头,即:

  • private headers of your project?
  • headers of your project, but which are exporting symbols (and thus, "public")
  • headers of another project your module links with
  • headers of a compiler or standard library
  • 您项目的私人标题?
  • 项目的标题,但导出符号(因此,“公共”)
  • 您的模块链接的另一个项目的标题
  • 编译器或标准库的头文件

For each kind of headers:

对于每种标题:

2.a: Would you use <> or "" ?
2.b: Would you include with {TheProject/TheHeader.hpp}, or with {TheHeader.hpp} only?

2.a:你会使用 <> 还是 "" ?
2.b:你会包含在 {TheProject/TheHeader.hpp} 中,还是只包含在 {TheHeader.hpp} 中?

3 - Bonus

3 - 奖金

3.a: Do you work on project with sources and/or headers within a tree-like organisation (i.e., directories inside directories, as opposed to "every file in one directory") and what are the pros/cons?

3.a:您是否在树状组织(即目录中的目录,而不是“一个目录中的每个文件”)中处理带有源和/或标题的项目,其优缺点是什么?

回答by paercebal

After reading all answers, as well as compiler documentation, I decided I would follow the following standard.

在阅读了所有答案以及编译器文档后,我决定遵循以下标准。

For all files, be them project headers or external headers, always use the pattern:

对于所有文件,无论是项目标头还是外部标头,始终使用以下模式:

#include <namespace/header.hpp>

The namespace being at least one directory deep, to avoid collision.

命名空间至少是一个目录深,以避免冲突。

Of course, this means that the project directory where the project headers are should be added as "default include header" to the makefile, too.

当然,这意味着项目头所在的项目目录也应该作为“默认包含头”添加到 makefile 中。

The reason for this choice is that I found the following information:

之所以做出这样的选择,是因为我找到了以下信息:

1. The include "" pattern is compiler-dependent

1. include "" 模式依赖于编译器

I'll give the answers below

我会在下面给出答案

1.a The Standard

1.a 标准

Source:

来源:

  • C++14 工作草案 n3797:https://isocpp.org/files/papers/N3797.pdf
  • C++11、C++98、C99、C89(引用的部分在所有这些标准中都没有变化)

In the section 16.2 Source file inclusion, we can read that:

在 16.2 源文件包含部分,我们可以看到:

A preprocessing directive of the form

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

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

形式的预处理指令

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

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

This means that #include <...> will search a file in an implementation defined manner.

这意味着 #include <...> 将以实现定义的方式搜索文件。

Then, the next paragraph:

然后,下一段:

A preprocessing directive of the form

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

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

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

with the identical contained sequence (including > characters, if any) from the original directive.

形式的预处理指令

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

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

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

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

This means that #include "..." will search a file in an implementation defined manner and then, if the file is not found, will do another search as if it had been an #include <...>

这意味着 #include "..." 将以实现定义的方式搜索文件,然后,如果未找到该文件,则会进行另一次搜索,就好像它是一个 #include <...>

The conclusion is that we have to read the compilers documentation.

结论是我们必须阅读编译器文档。

Note that, for some reason, nowhere in the standards the difference is made between "system" or "library" headers or other headers. The only difference seem that #include <...> seems to target headers, while #include "..." seems to target source (at least, in the english wording).

请注意,出于某种原因,标准中没有任何地方区分“系统”或“库”标题或其他标题。唯一的区别似乎是 #include <...> 似乎针对标题,而 #include "..." 似乎针对源(至少,在英文措辞中)。

1.b Visual C++:

1.b Visual C++:

Source:

来源:

#include "MyFile.hpp"

#include "MyFile.hpp"

The preprocessor searches for include files in the following order:

预处理器按以下顺序搜索包含文件:

  1. In the same directory as the file that contains the #include statement.
  2. In the directories of any previously opened include files in the reverse order in which they were opened. The search starts from the directory of the include file that was opened last and continues through the directory of the include file that was opened first.
  3. Along the path specified by each /I compiler option.
  4. (*) Along the paths specified by the INCLUDE environment variable or the development environment default includes.
  1. 与包含#include 语句的文件位于同一目录中。
  2. 在任何以前打开的包含文件的目录中,它们的顺序与它们打开的顺序相反。搜索从最后打开的包含文件的目录开始,并通过最先打开的包含文件的目录继续。
  3. 沿着每个 /I 编译器选项指定的路径。
  4. (*) 沿着由 INCLUDE 环境变量或开发环境默认包含指定的路径。

#include <MyFile.hpp>

#include <MyFile.hpp>

The preprocessor searches for include files in the following order:

预处理器按以下顺序搜索包含文件:

  1. Along the path specified by each /I compiler option.
  2. (*) Along the paths specified by the INCLUDE environment variable or the development environment default includes.
  1. 沿着每个 /I 编译器选项指定的路径。
  2. (*) 沿着由 INCLUDE 环境变量或开发环境默认包含指定的路径。

Note about the last step

关于最后一步的注意事项

The document is not clear about the "Along the paths specified by the INCLUDE environment variable" part for both <...>and "..."includes. The following quote makes it stick with the standard:

该文档不是明确了“沿着由指定的路径包括环境变量”部分两者<...>"..."包括。以下引用使其符合标准:

For include files that are specified as #include "path-spec", directory searching begins with the directory of the parent file and then proceeds through the directories of any grandparent files. That is, searching begins relative to the directory that contains the source file that contains the #include directive that's being processed. If there is no grandparent file and the file has not been found, the search continues as if the file name were enclosed in angle brackets.

对于指定为 #include "path-spec" 的包含文件,目录搜索从父文件的目录开始,然后通过任何祖父文件的目录进行。也就是说,搜索是相对于包含正在处理的 #include 指令的源文件的目录开始的。如果没有祖父文件并且未找到该文件,则继续搜索,就像文件名被括在尖括号中一样。

The last step (marked by an asterisk) is thus an interpretation from reading the whole document.

因此,最后一步(用星号标记)是阅读整个文档的解释。

1.c g++

1.c g++

Source:

来源:

The following quote summarizes the process:

以下引述总结了该过程:

GCC [...] will look for headers requested with #include <file>in [system directories] [...] All the directories named by -I are searched, in left-to-right order, before the default directories

GCC looks for headers requested with #include "file" first in the directory containing the current file, then in the directories as specified by -iquote options, then in the same places it would have looked for a header requested with angle brackets.

GCC [...] 将<file>在 [系统目录] [...] 中查找用 #include 请求的头文件

GCC 首先在包含当前文件的目录中查找使用 #include "file" 请求的头文件,然后在 -iquote 选项指定的目录中查找,然后在相同的位置查找使用尖括号请求的头文件。

#include "MyFile.hpp"

#include "MyFile.hpp"

This variant is used for header files of your own program. The preprocessor searches for include files in the following order:

此变体用于您自己程序的头文件。预处理器按以下顺序搜索包含文件:

  1. In the same directory as the file that contains the #include statement.
  2. Along the path specified by each -iquote compiler option.
  3. As for the #include <MyFile.hpp>
  1. 与包含#include 语句的文件位于同一目录中。
  2. 沿着每个 -iquote 编译器选项指定的路径。
  3. 至于#include <MyFile.hpp>

#include <MyFile.hpp>

#include <MyFile.hpp>

This variant is used for system header files. The preprocessor searches for include files in the following order:

此变体用于系统头文件。预处理器按以下顺序搜索包含文件:

  1. Along the path specified by each -I compiler option.
  2. Inside the system directories.
  1. 沿着每个 -I 编译器选项指定的路径。
  2. 在系统目录内。

1.d Oracle/Sun Studio CC

1.d Oracle/Sun Studio CC

Source:

来源:

Note that the text contradict itself somewhat (see the example to understand). The key phrase is: "The difference is that the current directory is searched only for header files whose names you have enclosed in quotation marks."

注意文字有些自相矛盾(看例子理解)。关键短语是:“不同的是,当前目录只搜索名称用引号括起来的头文件。

#include "MyFile.hpp"

#include "MyFile.hpp"

This variant is used for header files of your own program. The preprocessor searches for include files in the following order:

此变体用于您自己程序的头文件。预处理器按以下顺序搜索包含文件:

  1. The current directory (that is, the directory containing the “including” file)
  2. The directories named with -I options, if any
  3. The system directory (e.g. the /usr/include directory)
  1. 当前目录(即包含“包含”文件的目录)
  2. 使用 -I 选项命名的目录(如果有)
  3. 系统目录(例如 /usr/include 目录)

#include <MyFile.hpp>

#include <MyFile.hpp>

This variant is used for system header files. The preprocessor searches for include files in the following order:

此变体用于系统头文件。预处理器按以下顺序搜索包含文件:

  1. The directories named with -I options, if any
  2. The system directory (e.g. the /usr/include directory)
  1. 使用 -I 选项命名的目录(如果有)
  2. 系统目录(例如 /usr/include 目录)

1.e XL C/C++ Compiler Reference - IBM/AIX

1.e XL C/C++ 编译器参考 - IBM/AIX

Source:

来源:

Both documents are titled "XL C/C++ Compiler Reference" The first document is older (8.0), but is easier to understand. The second is newer (12.1), but is a bit more difficult to decrypt.

这两个文档的标题都是“XL C/C++ Compiler Reference”。第一个文档较旧(8.0),但更容易理解。第二个是较新的(12.1),但更难解密。

#include "MyFile.hpp"

#include "MyFile.hpp"

This variant is used for header files of your own program. The preprocessor searches for include files in the following order:

此变体用于您自己程序的头文件。预处理器按以下顺序搜索包含文件:

  1. The current directory (that is, the directory containing the “including” file)
  2. The directories named with -I options, if any
  3. The system directory (e.g. the /usr/vac[cpp]/include or /usr/include directories)
  1. 当前目录(即包含“包含”文件的目录)
  2. 使用 -I 选项命名的目录(如果有)
  3. 系统目录(例如 /usr/vac[cpp]/include 或 /usr/include 目录)

#include <MyFile.hpp>

#include <MyFile.hpp>

This variant is used for system header files. The preprocessor searches for include files in the following order:

此变体用于系统头文件。预处理器按以下顺序搜索包含文件:

  1. The directories named with -I options, if any
  2. The system directory (e.g. the /usr/vac[cpp]/include or /usr/include directory)
  1. 使用 -I 选项命名的目录(如果有)
  2. 系统目录(例如 /usr/vac[cpp]/include 或 /usr/include 目录)

1.e Conclusion

1.e 结论

The pattern "" could lead to subtle compilation error across compilers, and as I currently work both on Windows Visual C++, Linux g++, Oracle/Solaris CC and AIX XL, this is not acceptable.

模式 "" 可能会导致编译器之间的细微编译错误,而且由于我目前在 Windows Visual C++、Linux g++、Oracle/Solaris CC 和 AIX XL 上工作,这是不可接受的。

Anyway, the advantage of "" described features are far from interesting anyway, so...

无论如何,“”描述的特征的优势无论如何都远非有趣,所以......

2. Use the {namespace}/header.hpp pattern

2. 使用 {namespace}/header.hpp 模式

I saw at work (i.e. this is not theory, this is real-life, painful professional experience) two headers with the same name, one in the local project directory, and the other in the global include.

我在工作中看到(即这不是理论,这是现实生活,痛苦的职业经历)两个同名的header,一个在本地项目目录中,另一个在全局include中。

As we were using the "" pattern, and that file was included both in local headers and global headers, there was no way to understand what was really going on, when strange errors appeared.

由于我们使用了 "" 模式,并且该文件同时包含在本地头文件和全局头文件中,因此当出现奇怪的错误时,无法理解真正发生了什么。

Using the directory in the include would have saved us time because the user would have had to either write:

使用包含中的目录可以节省我们的时间,因为用户必须编写:

#include <MyLocalProject/Header.hpp>

or

或者

#include <GlobalInclude/Header.hpp>

You'll note that while

你会注意到,虽然

#include "Header.hpp"

would have compiled successfully, thus, still hiding the problem, whereas

会编译成功,因此,仍然隐藏问题,而

#include <Header.hpp>

would not have compiled in normal circonstances.

在正常情况下不会编译。

Thus, sticking to the <> notation would have made mandatory for the developer the prefixing of the include with the right directory, another reason to prefer <> to "".

因此,坚持使用 <> 符号会使开发人员强制使用正确的目录作为包含的前缀,这是更喜欢 <> 而不是 "" 的另一个原因。

3. Conclusion

3. 结论

Using both the <> notation and namespaced notation together removes from the pre-compiler the possibility to guess for files, instead searching only the default include directories.

同时使用 <> 符号和命名空间符号可以从预编译器中消除猜测文件的可能性,而不是只搜索默认的包含目录。

Of course, the standard libraries are still included as usual, that is:

当然,标准库还是照常包含的,即:

#include <cstdlib>
#include <vector>

回答by Evan Teran

I typically use <> for system headers and "" for project headers. As for paths, that is only neccessary if the file you want is in a sub-directory of an include path.

我通常使用 <> 作为系统标题,使用 "" 作为项目标题。至于路径,仅当您想要的文件位于包含路径的子目录中时才需要这样做。

for example, if you need a file in /usr/include/SDL/, but only /usr/include/ is in your include path, then you could just use:

例如,如果您需要 /usr/include/SDL/ 中的文件,但只有 /usr/include/ 在您的包含路径中,那么您可以使用:

#include <SDL/whatever.h>

Also, keep in mind that unless the path you put starts with a /, it is relative to the current working directory.

另外,请记住,除非您放置的路径以 / 开头,否则它是相对于当前工作目录的。

EDIT TO ANSWER COMMENT: It depends, if there is only a few includes for a library, I'd just include it's subdirectory in the include path, but if the library has many headers (like dozens) then I'd prefer to just have it in a subdir that I specify. A good example of this is Linux's system headers. You use them like:

编辑回答评论:这取决于,如果一个库只有几个包含,我只会在包含路径中包含它的子目录,但是如果库有很多头(比如几十个),那么我宁愿只拥有它在我指定的子目录中。一个很好的例子是 Linux 的系统头文件。您可以像这样使用它们:

#include <sys/io.h>
#include <linux/limits.h>

etc.

等等。

EDIT TO INCLUDE ANOTHER GOOD ANSWER: also, if it is conceivable that two or more libraries provide headers by the same name, then the sub-directory solution basically gives each header a namespace.

编辑以包括另一个好的答案:另外,如果可以想象两个或多个库提供同名的头文件,那么子目录解决方案基本上为每个头文件提供了一个命名空间。

回答by Michael Burr

To quote from the C99 standard (at a glance the wording appears to be identical in the C90 standard, but I can't cut-n-paste from that):

引用 C99 标准(乍一看,C90 标准中的措辞似乎相同,但我无法从中剪切和粘贴):

A preprocessing directive of the form

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

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

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

with the identical contained sequence (including > characters, if any) from the original directive.

形式的预处理指令

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

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

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

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

So the locations searched by #include "whatever"is a super-set of the locations searched by #include <whatever>. The intent is that the first style would be used for headers that in general "belong" to you, and the second method would be used for headers that "belong" to the compiler/environment. Of course, there are often some grey areas - which should you use for Boost headers, for example? I'd use #include <>, but I wouldn't argue too much if someone else on my team wanted #include "".

所以搜索到的位置是搜索到的位置#include "whatever"的超集#include <whatever>。目的是第一种样式将用于通常“属于”您的标头,而第二种方法将用于“属于”编译器/环境的标头。当然,通常有一些灰色区域 - 例如,您应该将哪些用于 Boost 标头?我会使用#include <>,但如果我团队中的其他人想要,我不会争论太多#include ""

In practice, I don't think anyone pays much attention to which form is used as long as the build doesn't break. I certainly don't recall it ever being mentioned in a code review (or otherwise, even).

在实践中,只要构建没有中断,我认为没有人会过多关注使用哪种形式。我当然不记得它曾经在代码中被提及(或者甚至没有)。

回答by Trent

I'll tackle the second part of your question:

我将解决您问题的第二部分:

I normally use <project/libHeader.h>when I am including headers from a 3rd party. And "myHeader.h"when including headers from within the project.

我通常<project/libHeader.h>在包含来自 3rd 方的标题时使用。而"myHeader.h"包括从项目内头时。

The reason I use <project/libHeader.h>instead of <libHeader.h>is because it's possible that more than one library has a "libHeader.h" file. In order to include them both you need the library name as part of the included filename.

我使用<project/libHeader.h>而不是的原因<libHeader.h>是因为可能不止一个库有一个“libHeader.h”文件。为了将它们都包含在内,您需要将库名称作为包含文件名的一部分。

回答by Trent

1.a: What are the differences between the two notations?

1.a:这两种符号有什么区别?

"" starts search in the directory where C/C++ file is located. <> starts search in -I directories and in default locations (such as /usr/include). Both of them ultimately search the same set of locations, only the order is different.

"" 在 C/C++ 文件所在的目录中开始搜索。<> 在 -I 目录和默认位置(例如 /usr/include)中开始搜索。它们最终都搜索同一组位置,只是顺序不同。

1.b: Do all compilers implement them the same way?

1.b:所有编译器都以相同的方式实现它们吗?

I hope so, but I am not sure.

我希望如此,但我不确定。

1.c: When would you use the <>, and when would you use the "" (i.e. what are the criteria you would use to use one or the other for a header include)?

1.c:什么时候使用<>,什么时候使用“”(即,您将使用一个或另一个作为标题包含的标准是什么)?

I use "" when the include file is supposed to be next to C file, <> in all other cases. IN particular, in our project all "public" include files are in project/include directory, so I use <> for them.

当包含文件应该在 C 文件旁边时,我使用 "",在所有其他情况下使用 <>。特别是,在我们的项目中,所有“公共”包含文件都在 project/include 目录中,因此我对它们使用 <>。

2 - #include {TheProject/TheHeader.hpp} or {TheHeader.hpp} ?

2 - #include {TheProject/TheHeader.hpp} 或 {TheHeader.hpp} ?

As already pointed out, xxx/filename.h allows you to do things like diskio/ErrorCodes.h and netio/ErrorCodes.h

正如已经指出的,xxx/filename.h 允许您执行诸如 diskio/ErrorCodes.h 和 netio/ErrorCodes.h 之类的操作

* private headers of your project?

*您项目的私人标题?

Private header of my subsystem in project. Use "filename.h" Public header of my subsystem in project (not visible outside the project, but accessible to other subsystems). Use or , depending on the convention adapted for the project. I'd rather use

项目中我的子系统的私有头文件。在项目中使用我的子系统的“filename.h”公共头文件(在项目外不可见,但其他子系统可以访问)。使用 或 ,具体取决于适用于项目的约定。我宁愿用

* headers of your project, but which are exporting symbols (and thus, "public")

* 您的项目的标题,但它们正在导出符号(因此,“公共”)

include exactly like the users of your library would include them. Probably

包含与您图书馆的用户将包含的完全一样。大概

* headers of another project your module links with

*您的模块链接的另一个项目的标题

Determined by the project, but certainly using <> * headers of a compiler or standard library Definitely <>, according to standard.

由项目决定,但肯定使用<> * 编译器或标准库的头文件 绝对<>,根据标准。

3.a: Do you work on project with sources and/or headers within a tree-like organisation (i.e., directories inside directories, as opposed to "every file in one directory") and what are the pros/cons?

3.a:您是否在树状组织(即目录中的目录,而不是“一个目录中的每个文件”)中处理带有源和/或标题的项目,其优缺点是什么?

I do work on a structured project. As soon as you have more than a score of files, some division will become apparent. You should go the way the code is pulling you.

我确实在一个结构化的项目上工作。一旦您的文件超过了分数,某些划分就会变得明显。你应该按照代码拉你的方式去做。

回答by John Dibling

Re <> vs "". At my shop, I'm very hands-off as far as matters of "style" are concerned. One of the few areas where I have a requirement is with the use of angle brackets in #include statements -- the rule is this: if you are #including an operating system or compiler file, you may use angle brackets if appropriate. In all other cases, they are forbidden. If you are #including a file written either by someone here or a 3rd party library, <> is forbidden.

Re <> vs ""。在我的店里,就“风格”问题而言,我非常不干涉。我需要的少数几个方面之一是在#include 语句中使用尖括号——规则是这样的:如果您#include 一个操作系统或编译器文件,您可以在适当的情况下使用尖括号。在所有其他情况下,它们是被禁止的。如果你 #include 一个由这里的某个人或第三方库编写的文件,<> 是被禁止的。

The reason is this: #include "x.h" and #include don't search the same paths. #include will only search the system path and whatever you have -i'ed in. Importantly, it will not search the path where the file x.h is located, if that directory isn't included in the search path in some other way.

原因是:#include "xh" 和 #include 不搜索相同的路径。#include 将只搜索系统路径和您输入的任何内容。重要的是,它不会搜索文件 xh 所在的路径,如果该目录未以其他方式包含在搜索路径中。

For example, suppose you have the following files:

例如,假设您有以下文件:

c:\dev\angles\main.cpp

c:\dev\angles\main.cpp

#include "c:\utils\mylib\mylibrary.h"

int main()
{
    return 0;
}

c:\utils\mylib\mylibrary.h

c:\utils\mylib\mylibrary.h

#ifndef MYLIB_H
#define MYLIB_H

#include <speech.h>

namespace mylib
{
    void Speak(SpeechType speechType);  
};

#endif

c:\utils\mhlib\speech.h

c:\utils\mhlib\speech.h

#ifndef SPEECH_H
#define SPEECH_H

namespace mylib
{
    enum SpeechType {Bark, Growl};
};

#endif

This will not compile without changing the path either by setting the PATH environment variable or -i'ing in the c:\utils\mhlib\ directory. The compiler won't be able to resove #include <speech.h>even though that file is in the same directory as mylibrary.h!

如果不通过设置 PATH 环境变量或 -i'ing 在 c:\utils\mhlib\ 目录中更改路径,这将无法编译。编译器将无法resove#include <speech.h>即使该文件是在同一目录mylibrary.h

We make extensive use of relative and absolute pathnames in #include statements in our code, for two reasons.

我们在代码中的#include 语句中广泛使用相对和绝对路径名,原因有二。

1) By keeping libraries and components off the main source tree (ie, putting utility libraries in a special directory), we don;t couple the lifecycle of the library to the lifecycle of the application. This is particularly important when you have several distinct products that use common libraries.

1) 通过使库和组件远离主源树(即,将实用程序库放在特殊目录中),我们不会将库的生命周期与应用程序的生命周期耦合。当您有多个使用公共库的不同产品时,这一点尤其重要。

2) We use Junctionsto map a physical location on the hard drive to a directory on a logical drive, and then use a fully-qualified path on the logical drive in all #includes. For example:

2)我们使用Junctions将硬盘上的物理位置映射到逻辑驱动器上的目录,然后在所有#includes 中使用逻辑驱动器上的完全限定路径。例如:

#include "x:\utils\mylib.h"-- good, x: is a subst'ed drive, and x:\utils points to c:\code\utils_1.0 on the hard drive

#include "x:\utils\mylib.h"-- 好的,x: 是替换驱动器,x:\utils 指向硬盘上的 c:\code\utils_1.0

#include "c:\utils_1.0\mylib.h"-- bad! the application tha t#includes mylib.h is now coupled to a specific version of the MYLIB library, and all developers must have it on the same directory on thier hard drive, c:\utils_1.0

#include "c:\utils_1.0\mylib.h"- 坏的!t#includes mylib.h 的应用程序现在耦合到特定版本的 MYLIB 库,并且所有开发人员都必须将它放在他们硬盘驱动器上的同一目录中,c:\utils_1.0

Finally, a broad but difficult to achieve goal of my team is to be able to support 1-click compiles. This includes being able to compile the main source tree by doing nothing more than getting code from source control and then hitting 'compile'. In particular, I abhor having to set paths & machine-wide #include directories in order to be able to compile, because every little additional step you add to the set-up phase in buildign a development machine just makes it harder, easier to mess up, and it takes longer to get a new machine up to speed & generating code.

最后,我团队的一个广泛但难以实现的目标是能够支持一键编译。这包括能够通过从源代码管理中获取代码然后点击“编译”来编译主源代码树。特别是,我讨厌必须设置路径和机器范围的 #include 目录才能进行编译,因为您在构建开发机器的设置阶段添加的每一个小额外步骤只会让它变得更难,更容易弄乱了,并且需要更长的时间才能让新机器加快速度并生成代码。

回答by coppro

There are two primary differences between <>and "". The first is which character will end the name - there are no escape sequences in header names, and so you may be forced to do #include <bla"file.cpp>or "bla>file.cpp". That probably won't come up often, though. The other difference is that system includes aren't supposed to occur on "", just <>. So #include "iostream"is not guaranteed to work; #include <iostream>is. My personal preference is to use ""for files that are part of the project, and <>for files that aren't. Some people only use <>for standard library headers and ""for all else. Some people even use <>only for Boost and std; it depends on the project. Like all style aspects, the most important thing is to be consistent.

<>和之间有两个主要区别""。第一个是名称结束的字符 - 标题名称中没有转义序列,因此您可能被迫执行#include <bla"file.cpp>"bla>file.cpp"。不过,这可能不会经常出现。另一个区别是系统包含不应该发生在"",只是<>。所以#include "iostream"不能保证工作;#include <iostream>是。我个人的偏好是""用于属于项目<>的文件,以及不属于项目的文件。有些人只<>用于标准库头文件和""其他所有内容。有些人甚至<>只用于 Boost 和 std;这取决于项目。像所有风格方面一样,最重要的是要保持一致。

As for the path, an external library will specify the convention for headers; e.g. <boost/preprocessor.hpp><wx/window.h><Magic++.h>. In a local project, I would write all paths relative to the top-level srcdir (or in a library project where they are different, the include directory).

至于路径,外部库会指定头文件的约定;例如<boost/preprocessor.hpp><wx/window.h><Magic++.h>。在本地项目中,我会编写相对于顶级 srcdir 的所有路径(或在它们不同的库项目中,包括目录)。

When writing a library, you may also find it helpful to use <> to differentiate between private and public headers, or to not -Ithe source directory, but the directory above, so you #include "public_header.hpp"and "src/private_header.hpp". It's really up to you.

在编写库时,您可能还会发现使用 <> 来区分私有和公共头文件很有帮助,或者不是-I源目录而是上面的目录,因此您#include "public_header.hpp""src/private_header.hpp". 这真的取决于你。

EDIT: As for projects with directory structures, I would highly recommend them. Imagine if all of boost were in one directory (and no subnamespaces)! Directory structure is good because it lets you find files easier, and it allows you more flexibility in naming ("module\_text\_processor.hpp"as opposed to "module/text\_processor.hpp"). The latter is more natural and easier to use.

编辑:对于具有目录结构的项目,我强烈推荐它们。想象一下,如果所有 boost 都在一个目录中(并且没有子命名空间)!目录结构很好,因为它可以让您更轻松地查找文件,并且可以让您更灵活地命名("module\_text\_processor.hpp"而不是"module/text\_processor.hpp")。后者更自然,更易于使用。

回答by J.J.

If I remember right.

如果我没记错的话。

You use the diamond for all libraries that can be found in your "path". So any library that is in the STL, or ones that you have installed. In Linux your path is usually "/usr/include", in windows I am not sure, but I would guess it is under "C:\windows".

您将菱形用于可以在您的“路径”中找到的所有库。因此,STL 中的任何库或您已安装的库。在 Linux 中,您的路径通常是“/usr/include”,在 Windows 中我不确定,但我猜它在“C:\windows”下。

You use the "" then to specify everything else. "my_bla.cpp" with no starting directory information will resolve to the directory your code is residing/compiling in. or you can also specify the exact location of your include with it. Like this "c:\myproj\some_code.cpp"

您可以使用 "" then 来指定其他所有内容。没有起始目录信息的“my_bla.cpp”将解析到您的代码所在/编译的目录。或者您也可以指定包含的确切位置。像这样“c:\myproj\some_code.cpp”

The type of header doesn't matter, just the location.

标题的类型无关紧要,只是位置。

回答by James Curran

I use <...> from system header file (stdio, iostreams, string etc), and "..." for headers specific to that project.

我使用系统头文件(stdio、iostreams、字符串等)中的 <...> 和“...”作为特定于该项目的头文件。

回答by Brian Stewart

We use #include "header.h" for headers local to the project and #include for system includes, third party includes, and other projects in the solution. We use Visual Studio, and it's much easier to use the project directory in a header include, this way whenever we create a new project, we only have to specify the include path for the directory containing all the project directories, not a separate path for each project.

我们使用 #include "header.h" 作为项目本地的标头,#include 用于系统包含、第三方包含和解决方案中的其他项目。我们使用Visual Studio,在头包含中使用项目目录要容易得多,这样每当我们创建一个新项目时,我们只需要为包含所有项目目录的目录指定包含路径,而不是单独的路径每个项目。