C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)
Posted 昊虹图像算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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"不会被预编译处理。
以上是关于C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)的主要内容,如果未能解决你的问题,请参考以下文章