文件相互包含的错误问题
- 序言
- 可能会有的疑问
- 原因分析
- C2504: 未定义的基类
- C2143: 语法错误: 缺少“;”(在“*”的前面)
- C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
- C2238: 意外的标记位于“;”之前
- 解决方案
序言
文件相互包含的错误问题实际是两个类相互包含,从而引起的声明先后问题
可能会有的疑问
1、头文件里明明有Header Guards(防卫式声明):
#ifdef
#define
#endif
怎么还会产生所谓的文件相互包含的问题呢?
溪渣渣:Header Guards(防卫式声明)确实有效防止头文件重复包含,但也引出了本章实际错误:两个类相互包含
原因分析
C2504: 未定义的基类
其实这个原因是因为编译基类的h文件中,包含了派生类的h文件,导致派生类在基类之前就已经声明,但是虽然提前声明,可基类依然还是没有声明。
光看文字是很苍白无力的,我举个例子
//AA.h
#ifndef AA_H
#define AA_H#include "BB.h"class AA
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
...
};
#endif
//BB.h
#ifndef BB_H
#define BB_H#include "AA.h"class BB :public AA
{
...
};
#endif
说到这,就不得不说#include “”/<>的本质了,这实质是把对应的h文件内容copy过来放到该头文件里面,所以实际是这样的:
在编译AA.h时,其实际头文件是:
//AA.h
#ifndef AA_H
#define AA_H//BB.h
#ifndef BB_H
#define BB_H#ifndef AA_H //已有宏定义,所以再次包含的不编译
...
#endifclass BB :public AA //BB要编译,就需要AA类,但AA类在后面,等同于AA类并没有任何声明,故报错 C2504: 未定义的基类
{
...
};
#endifclass AA
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
...
};
#endif
.
C2143: 语法错误: 缺少“;”(在“*”的前面)
C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
C2238: 意外的标记位于“;”之前
该原因是因为AA包含的BB类,没有在AA之前声明,所以"BB"等同于不存在的符号,因此报错。
在编译BB.h时,其实际头文件是:
//BB.h
#ifndef BB_H
#define BB_H//AA.h
#ifndef AA_H
#define AA_H#ifndef BB_H //已有宏定义,所以再次包含的不编译
...
#endif//AA要想成功声明,首先就需要包含有的BB类的声明了,毕竟BB不存在的话,AA就无法成功声明,所以等同于
class AA //BB只是个乱写的符号,所以编译器无法识别,所以会报上面的错误
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
...
};
#endifclass BB :public AA
{
...
};
#endif
解决方案
以上面为例
//AA.h
#ifndef AA_H
#define AA_Hclass BB;class AA
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
...
};
#endif
//AA.cpp
#include "AA.h"
#include "BB.h"...
#endif
BB.h不用改,因为AA.h已经可以成功声明了,BB.h可以正常声明了。
为什么在前面放个class,然后在cpp里面放#include ""就行了呢?
简单来说,就是头文件的只需要个声明,用到类的结构如cpp里才需要#include “”,这就好像下文提前声明一样的道理。
int func();void fun()
{cout << func();
}int func()
{return 5;
}
在其代入其实是每个cpp文件编译的情况时,你就明白了
值得注意的是,在AA.h里直接BB b或者调用b->func()等操作是不对的,这样头文件里就不是个声明了,是用到类的结构,就算前置了声明也无效,因为实际的定义在后面还没有实际定义好,只需要改为指针BB *暂时替代,在AA.cpp再行#include "BB.h"进行相关对BB的操作即可。