飞道的博客

【C++】C++中防止头文件重复包含的两种方法

317人阅读  评论(0)

01、错误分析:类型重定义(头文件重复包含)

现象:

#include文件的一 个不利之处在于一个头文件可能会被多次包含,为了说明这种错误,考虑下面的代码:

#include "Index.h"
#include "Index.h"

//当前实际开发中没人会这么写程序,但是我们换一种写法

常犯错误如下:

//#include "MaxFile.h"
#include "Index.h"
//#include "MinFile.h"
#include "Index.h"

MaxFile.hMinFile.h 都有包含 Index.h,这种情况,想必在做大型工程的时候比比皆是,都会犯这种错误,准确点说,这也不算错误,因为确实当前文件需要使用此头文件。但是就是由于这种很多头文件中都有使用某一个通用的头文件,就会导致头文件重复包含错误(类型重定义)

02、解决方案

这里有两种方案可以解决此问题,如下:
1、使用微软封装的宏。
2、使用C中的条件编译。
等下会介绍两种方式的好处与相较来说的坏处。

2.1、微软宏

Code:

#pragma once
/* 下面正常声明函数、类、结构体等操作 */

2.2、条件编译

Code:

#ifndef _INCLUDE_HEADER_
#define _INCLUDE_HEADER_
/* 下面正常声明函数、类、结构体等操作 */

#endif

2.3、两种方法比较

  1. 局限性:条件编译方式,适用于任何平台;微软宏,则被编译器限制,只能在Windows VS中使用。
  2. 效率性

条件编译:当头文件第一次被包含时,它被正常处理,符号_HEADERNAME_H被定义为1。如果头文件被再次包含,通过条件编译,它的内容被忽略。符号_HEADERNAME_H按照被包含头文件的文件名进行取名,以避免由于其他头文件使用相同的符号而引起的冲突。

微软宏:#pragma once指定当前文件在构建时只被包含(或打开)一次,这样就可以减少构建的时间,因为加入#pragma once后,编译器在打开或读取第一个#include 模块后,就不会再打开或读取随后出现的同#include 模块。

03、变量被重复包含

我们来说一说重复包含的影响:

C/C++在预处理的时候,include相同的文件,预处理器会检查XXX是否有定义再决定要不要复制内容,重复包含会是编译器多检查几次而已。另外在使用增量编译的时候,这个文件变化,所有 include 这个文件的文件都需要重新编译,即使没有去使用里面的任何内容,所以重复包含最经常带来的错误就是重定义

这就是为什么上面的错误会报重定义了

使用#ifndef只是防止了头文件被重复包含(其实本例中只有一个头文件,不会存在重复包含的问题),但是无法防止变量被重复定义。

由于工程中的每个.c文件都是独立的解释的,即使头文件有
#ifndef TEST_H
#define TEST_H

#enfif
在其他文件中只要包含了某个头文件例如:global.h就会独立的解释,然后每个.c文件生成独立的标示符。在编译器链接时,就会将工程中所有的符号整合在一起,由于文件中有重名变量,于是就出现了重复定义的错误。

3.1、解决办法

在.c文件中声明变量,然后建一个头文件(.h文件)在所有的变量声明前加上extern,注意这里不要对变量进行的初始化。然后在其他需要使用全局变量的.c文件中包含.h文件。编译器会为.c生成目标文件,然后链接时,如果该.c文件使用了全局变量,链接器就会链接到此.c文件 。

04、版权声明&总结

重定义:即多次定义,不论以什么样的方式出现,只要是****重定义,那么一定是什么地方出现了多次,导致程序自己都懵逼了。

版权声明:创作不易,转载请注明出处。


转载:https://blog.csdn.net/m0_43458204/article/details/116764348
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场