C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)

这篇博文是博文https://blog.csdn.net/wenhao_ir/article/details/125668051的配套博文。

头文件被重复包含是下面这样的现象:
A文件里包含了C文件,
B文件里也包含了C文件,
然后A文件又把B文件包含了进来。
这样,相当于A文件包含了两次C文件,这就是文件包含处理时文件被重复包含的问题。

文件包含时重复包含问题有时候会带来一些问题,典型的就是重定义问题,导致编译通不过,或者编译通过,但是程序运行结果不是我们想要的。

比如我们把上面这个现象实例化为一个例子:
有以下三个文件:
在这里插入图片描述

A.cpp
B.cpp
C.h

A.cpp中包含了文件B.cpp和文件C.h
B.cpp也包含了文件C.h

A.cpp中的内容如下:

# include<iostream>
using namespace std;

# include"C.h"
# include"B.cpp"

int main()
{


	cout << "kk is " << kk << endl;


	return 0;
}

C.h中的内容如下:

int kk = 100;

B.cpp中的内容如下:

# include"C.h"

int aa = 333;

这样我们在编译A.cpp时就会报错,如下图所示:
在这里插入图片描述
在这里插入图片描述
错误的原因在于A在引入C.h时对int型变量kk进行了一次定义,而A在引入B.cpp时由于B.cpp也引入了文件C.h,所以又对int型变量kk进行了一次定义。这样就造成了对int型变量kk的两次定义,这样编译器就报错了。

怎样解决重复包含问题呢?
最根本的方法就是自己在写代码时对项目的文件层次结构有个清晰的了解,然后进行精准控制。
比如上面的例子,如果对文件层次结构有个清晰的了解,那么我们便很容易通过修改相关文件内容把问题解决。

或者采用以下方法尽量避免重复包含的可能性。

方法一:采用条件宏定义(条件编译)
以上面的例子为例,我们对文件A.cpp和B.cpp加上条件宏定义,三个文件中的内容加上条件宏定义后如下:
A.cpp中的内容:

#include<iostream>
using namespace std;

#define HEADER_C

#include"C.h"
#include"B.cpp"

int main()
{


	cout << "kk is " << kk << endl;


	return 0;
}

C.h中的内容如下:

int kk = 100;

B.cpp中的内容如下:

#ifndef HEADER_C
#include"C.h"
#endif

int aa = 333;

通过上面的修改,就能顺利编译,并且正确运行了。
我们把上面的代码模拟预编译展开就知道为什么可以正确运行了:

#include<iostream>
using namespace std;

#define HEADER_C

int kk = 100;

#ifndef HEADER_C
#include"C.h"
#endif

int aa = 333;

int main()
{


	cout << "kk is " << kk << endl;


	return 0;
}

运行结果如下图所示:
在这里插入图片描述

方法二:使用语句#pragma once

语句#pragma once放在某个头文件的第一行,表明这个文件在被别的某个文件包含时只能包含一次。

将上面的例子中的C.h中的内容改成如下:

#pragma once

int kk = 100;

那么编译就能顺利通过,且能正确运行了。

为什么这样写可以,结合语句#pragma once的作用并把B.cpp的内容展开到A.cpp中就知道了,如下:

#include<iostream>
using namespace std;


#include"C.h"

#include"C.h"

int aa = 333;


int main()
{


	cout << "kk is " << kk << endl;


	return 0;
}

由于在C.h的第一行声明了这个文件只能被同一个源文件包含一次,所以第二个# include"C.h"不会被预编译处理。

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值