C++ 在c+中包含两次头文件+;

C++ 在c+中包含两次头文件+;,c++,header-files,C++,Header Files,如果我在文件中两次包含iostream或任何其他头文件,会发生什么情况? 我知道编译器不会抛出错误 代码会被添加两次还是会在内部发生什么 当我们包含头文件时,实际会发生什么情况?防止编译器实际看到文件内容两次 Include guard基本上是头文件开头和结尾的一组预处理器条件指令: #ifndef SOME_STRING_H #define SOME_STRING_H //... #endif 现在,如果您包含文件两次,则不会定义第一次循环宏的某些字符串,因此编译器会处理和查看文件的内

如果我在文件中两次包含
iostream
或任何其他头文件,会发生什么情况? 我知道编译器不会抛出错误

代码会被添加两次还是会在内部发生什么

当我们包含头文件时,实际会发生什么情况?

防止编译器实际看到文件内容两次

Include guard基本上是头文件开头和结尾的一组预处理器条件指令:

#ifndef SOME_STRING_H
#define SOME_STRING_H

//...

#endif 
现在,如果您包含文件两次,则不会定义第一次循环宏
的某些字符串
,因此编译器会处理和查看文件的内容。但是,由于
#ifdef
之后的第一件事是
#define
定义了一些字符串
,编译器看不到头文件的下一次内容


为避免冲突,include guard中使用的宏的名称取决于头文件的名称。

由于预处理器代码如下所示,它只是被跳过:

#ifndef MY_HEADER_H
#define MY_HEADER_H

<actual header code here>

#endif
\ifndef MY\u HEADER\u H
#定义我的标题
#恩迪夫

因此,如果包含两次,则已定义了
MY_HEADER\u H
,预处理器将跳过
#ifndef
#endif
之间的所有内容。

头文件很简单。当您
#include
时,所发生的一切就是
标题的内容基本上被粘贴到文件中。为了防止多次包含头文件,使用了
包含保护
,这就是为什么在大多数头文件中,您会看到类似于

#ifndef SOME_HEADER_FILE_GUARD 
#define SOME_HEADER_FILE_GUARD

//Contents of Header

#endif

视情况而定。除了
,本标准要求 第二个(以及更高版本)包括一个标准标题,该标题为no-op 然而,标题的特征;编译器将(至少) (概念上)每次阅读并包含所有标题文本 遇到的问题包括

在这种情况下避免多重定义的标准做法是 使用包含保护:头中的所有C++代码将是 用类似于:

#ifndef SPECIAL_NAME
#define SPECIAL_NAME
//  All of the C++ code here
#endif SPECIAL_NAME
显然,每个头都需要不同的名称。在应用程序中, 通常可以根据文件名和文件名建立约定 位置;类似于子系统的文件名
,带有 C++符号中的字符不合法(如果您在其中使用它们) 文件名)映射(通常所有内容都是大写的)。对于 在图书馆中,最好的做法是生成一个合理的长 字符的随机序列;更频繁(尽管肯定 (从实施质量的角度来看)是为了确保 每一个这样的符号都以一个记录在案的前缀开头

当然,系统库可以使用保留符号(例如符号 以下划线开头,后跟大写字母)到 保证没有冲突。或者它可以完全使用一些 不同的、依赖于实现的技术。比如微软,, 使用编译器扩展名
#pragma一次
;g++使用包括 始终以
\u GLIBCXX
开头(这在用户代码中不是合法符号)。
这些选项不一定对您可用。

包含头文件时,其所有内容都会复制到“#include”指令所在的行。这是由预处理器完成的,是编译过程中的一个步骤

对于标准文件(如iostream或存储在本地目录中的用户自制的“.h”文件),此过程是相同的。但是,语法略有不同

我们使用
#include
来处理存储在库中的像“iostream”这样的文件。然而,对于本地目录中的头文件,我们使用
#include“filename.h”

现在,如果我们包含两次头文件怎么办:

理想情况下,内容应该复制两次。但是

  • 许多头文件使用现代做法,即一次提及
    #pragma
    ,这指示预处理器仅复制一次内容,而不管头文件包含多少次

  • 一些非常古老的代码使用了一个称为“include gaurds”的概念。我不会解释它,因为其他答案做得很好


  • 使用
    pragma once
    是一种简单而现代的方法,但是,以前使用过很多include-guard,这是一个相对复杂的解决方案。

    很大的帮助::请注意:在使用Microsoft工具时,您经常会看到
    #pragma once
    ,它具有与
    #ifndef…
    相同的功能。为了更好地兼容编译器,您应该使用后者。还要注意的是,大多数编译器都会识别此模式,甚至在第二次看到文件时都不会打开它。这实际上并不能回答问题。我对原来的问题感兴趣,因为我在看别人的代码。