C/C++ 中头文件相互包含引发的问题

原地址:http://blog.csdn.net/hazir/article/details/38600419

我把问题脱离于项目简单描述一下:我写了一个函数 bool func(ClassA* CA) 需要加到项目中,我就把这个函数的声明放到 head1.h 中,函数参数类型 ClassA 定义在另一个头文件 head2.h 中,因此我需要在 head1.h 中包含 head2.h;而 head2.h 中之前又包含了 head1.h,这样就构成了一种头文件相互包含的场景。再加上一些其它的声明与定义,就构成了这样的一个文件结构:

-------head1.h

#ifndef __HEAD_1_H__
#define __HEAD_1_H__

#include "head2.h"

#define VAR_MACRO  1          //define a macro, which used in head2.h

bool func(ClassA* CA);        //ClassA is defined in head2.h

#endif 


---------- head2.h

#ifndef __HEAD_2_H__
#define __HEAD_2_H__

#include "head1.h"

class ClassA{
  int mVar;
  void setMem(){ mVar = VAR_MACRO };    //macro VAR_MACRO is defined in head1.h

  ...     //other members and functions
};

#endif 


那么,现在另有两个源文件

source1.cpp


#include "head1.h"
source2.cpp

#include "head2.h"


整个项目会分别编译这两个源文件,编译完之后会报错,大致意思是 ClassA 和 VAR_MACRO 没有定义,那么问题就比较奇怪了,每个头文件都分别引用了另一个头文件,为什么会出现未定义呢?

我们都知道 C/C++ 中头文件开始习惯使用 #ifndef ... #define ... #endif 这样的一组预处理标识符来防止重复包含,例如上面的问题中我也使用了,如果不使用的话,两个头文件相互包含,就出现递归包含。这个很好理解就不多叙。

回到问题本身,我在微博上贴出了这个问题,有人说在 head1.h 的函数前加上 ClassA A; 的前置声明,至于为什么要加,估计很多人都没理解...

对于 source1.cpp,它包含了头文件 head1.h,那么在编译之前,在 source1.cpp 中展开 head1.h,而 head1.h 又包含了 head2.h, 那么也展开它,这时 source1.cpp 就变成类似下面这样:

class ClassA{
  int mVar;
  void setMem(){ mVar = VAR_MACRO };    //macro VAR_MACRO is defined in head1.h

  ...     //other members and functions
};

#define VAR_MACRO  1          //define a macro, which used in head2.h

bool func(ClassA* CA);        //ClassA is defined in head2.h

//... source1.cpp source code

看到没,这地方 func 函数之前有 ClassA 类型的定义,根本没必要像有些人说的那样加上 ClassA CA; 这样的前置声明。

我们再展开 source2.cpp 看看:

#define VAR_MACRO  1          //define a macro, which used in head2.h

bool func(ClassA* CA);        //ClassA is defined in head2.h

class ClassA{
  int mVar;
  void setMem(){ mVar = VAR_MACRO };    //macro VAR_MACRO is defined in head1.h

  ...     //other members and functions
};

//... source2.cpp source code

这时问题就很清楚了,func 函数声明之前并没有发现 ClassA 类型定义,该定义在函数声明的后面,这时候如果能在head1.h 的函数声明之前加上 ClassA CA; 的前置声明,就不会在编译的时候报找不到 ClassA 的定义的错误了。

再回到 source1.cpp 展开的源码看看,是不是一下子明白了为什么报找不到 VAR_MACRO 的定义的错误了?修改方法也简单,把宏定义拉到 #include "head2.h" 语句之前就 OK 了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值