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

时间:2012-10-17 07:07:48

标签: c++ header-files

如果我在文件中包含iostream或任何其他头文件两次会怎样? 我知道编译器不会抛出错误。

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

当我们包含头文件时会发生什么?

5 个答案:

答案 0 :(得分:14)

Include guard可防止编译器实际看到文件内容两次。

包含保护基本上是一组预处理器的条件指令,位于头文件的开头和结尾:

#ifndef SOME_STRING_H
#define SOME_STRING_H

//...

#endif 

现在,如果您将文件包含两次,则第一次定义宏SOME_STRING_H未定义,因此编译器会处理并查看文件的内容。但是,由于#ifdef之后的第一件事是#define,因此SOME_STRING_H被定义,下一次编译器看不到头文件的内容。

为避免冲突,包含保护中使用的宏的名称取决于头文件的名称。

答案 1 :(得分:3)

头文件是简单的野兽。当您#include <header>发生的所有事情都是header的内容基本上被复制粘贴到文件中。要阻止多次包含标头,会使用include guards,这就是为什么在大多数标头文件中您会看到类似于

的内容
#ifndef SOME_HEADER_FILE_GUARD 
#define SOME_HEADER_FILE_GUARD

//Contents of Header

#endif

答案 2 :(得分:2)

由于以下几行的预处理程序代码,它只是被跳过:

#ifndef MY_HEADER_H
#define MY_HEADER_H

<actual header code here>

#endif

因此,如果您包含两次,则MY_HEADER_H已经定义,并且预处理器会跳过#ifndef#endif之间的所有内容。

答案 3 :(得分:1)

这取决于。除<assert>外,该标准要求使用 第二个(以及后面)包括一个标准的标题作为无操作。这是 然而,标题的特征;编译器将(至少 概念上)每次读取并包含所有标题文本 遇到包括。

在这种情况下避免多重定义的标准做法是 使用include guard:标题中的所有C ++代码都是 包含在以下内容中:

#ifndef SPECIAL_NAME
#define SPECIAL_NAME
//  All of the C++ code here
#endif SPECIAL_NAME

显然,每个标题都需要不同的名称。在一个应用程序中 你通常可以根据文件名建立约定 地点;像subsystem_filename这样的东西 C ++符号中不合法的字符(如果你在你的中使用它们) 映射的文件名(通常是大写的)。对于 图书馆,最佳做法是产生相当长的时间 随机字符序列;更频繁(虽然肯定 从执行质量的角度来看,是低于确保的 每个这样的符号都以记录的前缀开头。

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

答案 4 :(得分:0)

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

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

对于存储在库中的“ iostream”之类的文件,我们使用#include <filename>。而对于本地目录中的头文件,我们使用#include "filename.h"

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

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

  1. 许多头文件使用现代#pragma once提法,即指示预处理器仅复制一次内容,无论头文件包含多少次。

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

使用pragma once是一种简便且现代的方法,但是,包含防护措施在以前已经被广泛使用,并且是解决此问题的相对复杂的方法。