头文件保护符有什么作用?

在C++中我们写头文件时经常需要#include来包含其他头文件。头文件定义的实体经常使用其他头文件的内容,有时候会出现一个头文件被多次包含进同一源文件。

例如:一个头文件中用到string类型的变量,而包含这个头文件的源文件中也用到string类型的变量,这个时候string头文件就被包含了两次:一次是通过程序本身直接包含,另一次是通过包含自写头文件而间接包含。

因此,设计头文件的时候,应该使其可以多次包含在同一源文件中,这一点是很重要的。我们必须保证多次包含同一头文件不会引起该头文件的类和对象被多次定义。使得头文件安全的通用做法是使用预处理器定义的头文件保护符。头文件保护符用于避免在已经见到头文件的情况下重新处理该头文件的内容。

头文件保护符依赖于预处理变量

为了避免命名冲突,预处理器变量经常用全大写字母表示。预处理器变量有两种状态:一定义和未定义。定义预处理器变量和检测器状态所用的预处理器指示不同。

#define指示接受一个名字并定义该名字为预处理器变量。

#ifndef指示检测指定的预处理器变量是否未定义。如果预处理器变量未定义,那么跟在其后面的所有指示都被处理,直到出现#endif。

为了保证头文件在给定的源文件中只处理一次,我们首先检测#ifndef。第一次处理头文件时,测试会成功,因为相应的预处理器还未定义。下一条语句就定义了该预处理器变量。那样的话,如果我们编译的文件敲好又一次包含了该头文件,#ifndef指示会发现该预处理器已经定义,并且忽略该头文件的剩余部分。

应用示例:

C++中,一般我们会为了防止头文件被包含多次,都会在每个头文件中写与如下类似的代码:
#ifndef A_H
#define A_H
......//头文件内容
#endif
 
头文件第一次被包含时,因为没有宏定义过“A_H”,因此经过语句

#ifndef A_H
#define A_H

并得到执行后,“A_H”就被定义了,并且头文件的内容会进入编译,直到遇见“#endif”。
 
而一旦该头文件即将被错误地包含第二次时,与语句“#ifndef A_H”不符,因为第一次你已经定义过“A_H”了,所以“#ifndef A_H”之后的语句不会进入编译了,直到遇见“#endif”。
 
若头文件被包含一次以上,编译时都会报错。C++头文件保护符的目的就是避免这类错误。

C++ 头文件保护符的更多相关文章

  1. C++预处理和头文件保护符

    一预处理 1.常见的预处理功能 预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译.布局控制和宏替换4种.文件包含:#include 是一种最为常 ...

  2. C++编程规范之23:头文件应该自给自足

    摘要: 各司其责:应该确保所编写的每个头文件都能够独自进行编译,为此需要包含其内容所依赖的所有头文件. 如果一个文件包含某个头文件时,还要包含另一个头文件才能工作,就会增加交流障碍,给头文件的用户增添 ...

  3. 小猪猪逆袭成博士之C++基础篇(二) 常量、处理类型、自定义头文件

    小猪猪逆袭成博士之C++基础篇(二) const .auto. decltype 上一章我们介绍了一些常用的类型和常见的问题,下面再介绍一些学习的时候不是特别常用但是在实际工程中很有用的一些东西. 一 ...

  4. gcc编译时头文件和库文件搜索路径

    特殊情况:用户自定义的头文件使用#include"mylib"时,gcc编译器会从当前目录查找头文件 一.头文件 gcc 在编译时寻找所需要的头文件 :    ※搜寻会从-I开始( ...

  5. Makefile自动生成头文件依赖

    前言 Makefile自动生成头文件依赖是很常用的功能,本文的目的是想尽量详细说明其中的原理和过程. Makefile模板 首先给出一个本人在小项目中常用的Makefile模板,支持自动生成头文件依赖 ...

  6. c++中,保证头文件只被编译一次,避免多重包含的方法

    保证头文件只被编译一次 #pragma once这是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次. #pragma once是编译器相关的,有的编译器支 ...

  7. direct.h头文件(对目录操作)

    chdir()改变当前目录的函数原形:int chdir(const char *path)功能:把由path指定的目录改为当前目录.path参数中可以指定驱动器号,如“a:\\ddd”, 但只是改变 ...

  8. CONFIG_*头文件的配置

    通常在kernel或uboot中, 有很多以CONFIG_*开头的宏配置选项,并且保存在相应的头文件中,那么这些CONFIG_*是怎么生成的呢? 在uboot的顶层Makefile中,有这么一项: 此 ...

  9. 【C】.h头文件的重复包含问题

    .h头文件存在的意义就是封装,可以方便多个.c源文件使用,但要防止.h头文件被同一个.c源文件多次包含. 例如, io.h文件 #ifndef _IO_H_ #define _IO_H_ #defin ...

随机推荐

  1. Django笔记 —— 模板高级进阶

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  2. 27、理解js的继承机制(转载自阮一峰)

    Javascript继承机制的设计思想   作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...

  3. lessJs

    lessJs下载地址 ======== 简介 lessJs主要提供页面切换,页面管理的一个框架:less-ui.css 和 less-ui.js 是独立于less.js的,他们提供的是一组ui,包括消 ...

  4. Qt QML之不显示标题栏、边框

    原文连接:http://blog.csdn.net/u010780613 我使用的Qt版本是Qt 5.3.0,Qt Creator 是3.1.1. QML做界面实在太方便了,动画效果很不错. 创建一个 ...

  5. Vm Ubuntu 文件共享问题

    其实也是差不多的,就是需要重新安装一次工具 ,自己安装有问题,自己在手动安装一次就好了 下面是一个我的参考文章 http://blog.csdn.net/zz962/article/details/7 ...

  6. 序列化反序列化--Xstream的使用

    之前讲了fastjson的使用--将JavaBean与json对象之间互相转换. 该篇文章,教大家使用Xstream来实现XMl与JavaBean的转换. 第一步: 通过maven引入XStream的 ...

  7. javaX邮件发送

    /** * *  * @param mailServerHost 邮件服务器 * @param mailServerPort 端口 * @param validate 是否需要身份验证 * @para ...

  8. 剑指offer-数值的整数次方12

    class Solution: def Power(self, base, exponent): # write code here if base==0: return 0 if exponent= ...

  9. ubuntu安装显卡驱动和cuda

    NVIDIA-linux.run安装后,会出现登录页面循环,解决办法是在运行命令后加入-no-opengl-files 打开nvidia x server Settings软件,显示:You do n ...

  10. 好用的在线pdf转化器

    https://smallpdf.com/cn/compress-pdf