都是头文件的循环包含惹的祸

首先我们先建立一个项目,项目文件有:

A.h

B.h

C.h

A.cpp

B.cpp

C.cpp

 

文件内容如下:

A.h

#ifndef EVENTHANDLER_CEVENTHANDLER_H_HEADER_INCLUDED_BA392BB6

#define EVENTHANDLER_CEVENTHANDLER_H_HEADER_INCLUDED_BA392BB6

#include "B.h"

 

class A

{

public:

     B b;  //其实不应该用一个对象,应该用指针,这里只是为了说明问题

};

 

#endif

 

B.h

#ifndef EVENTHANDLER_CEVENTHANDLER_H_HEADER_INCLUDED_BA392BB6B

#define EVENTHANDLER_CEVENTHANDLER_H_HEADER_INCLUDED_BA392BB6B

#include "C.h"

 

class B

{

public:

};

 

#endif

 

C.h

#ifndef EVENTHANDLER_CEVENTHANDLER_H_HEADER_INCLUDED_BA392BB6C

#define EVENTHANDLER_CEVENTHANDLER_H_HEADER_INCLUDED_BA392BB6C

#include "A.h"

 

class C

{

public:

};

 

#endif

 

A.cpp

#include "A.h"

 

B.cpp

#include "B.h"

 

C.cpp

#include "C.h"

 

我们先做一个试验,分别注释掉A.cpp,B.cpp,C.cpp中的包含文件,每次只留下一个,比如第一次(A情况)注释掉:B.cpp,C.cpp中的包含文件语句,第二次(B情况)注释掉A.cpp,C.cpp中的包含文件语句,第三次(C情况)注释掉:A.cpp,C.cpp中的包含文件语句,便以结果如下表:

测试用例

编译结果

A

编译通过

B

编译出错syntax error : missing ';' before identifier 'b'

C

编译通过

 

为什么在B情况下会出现b标识符没有找到呢?我们来分别分析一下这几种情况:

A情况中只有 “A.cpp”文件中包含”A.h”,那么编译器开始首先编译”A.cpp”文件,它首先看到#include “A.h”语句,这时它并不是立刻展开”A.h”,而是会到”A.h”里再找是否有包含别的.h文件,如果有编译器则再到那个.h文件里再找是否有包含其他的.h文件,直到最低层,所以情况变成了在A.h中又找到#include “B.h”,然后又在”C.h”里找到#include “A.h”但此时A.h已经包含过一次了,所以跳出。最终在A.cpp文件里的内容可能是这样:

class C

{

public:

};

 

class B

{

public:

};

 

class A

{

public:

     B b;

};

 

B情况的分析过程与A类似,在B.cpp文件里的内容可能是这样:

class A

{

public:

     B b;

};

 

class C

{

public:

};

 

class B

{

public:

};

 

C情况的分析过程一样,在C.cpp文件里的内容可能是这样:

class B

{

public:

};

 

 

class A

{

public:

     B b;

};

 

class C

{

public:

};

 

经过上面的代码可以看出,显然B情况是错误的,而且确实B在出现以前并没有声明。

其实头文件包含过程很像一个栈的调用过程,编译器会去找文件中包含的那个头文件里是否包含其他的头文件,直到找到最底层头文件或没有包含头文件为止,然后再一层一层返回展开头文件里面的内容。

 

这篇文章的目的是为了说清楚头文件出现循环包含时,代码可能的呈现,因为只要你知道代码的呈现就很容易解决头文件循环包含的错误,就上上面变量没有找到的错误。文章仓促写成肯定会有错误,望大家多指正交流。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值