从自己的hi.baidu.com空间搬运过来,哪里的代码排版真的太难看了。。。。。
最近被一个看似诡异的事情卡壳,情况大概是这样,很明显的文件的开始添加了某个类的头文件,但是在代码中使用所添加的类时候却提示未定义该类。其中原因最后终于发现,原来是非常经典的错误——超前引用。
所谓超前引用,粗略的说就是两个类之间进行了交叉引用,举个最简单的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
//filename:A.h
#ifndef A_H
#define A_H
#include "B.h"
class
A{
public
:
A(){}
~A(){}
B b;
//A类中包含B的实例
//other codes
}
#endif //end A.h
//-------------------------------------------------------------
//filename:A.cpp
#include "A.h"
//这里实现A类中的方法,略
//end A.cpp
//--------------------------------------------------------------
//filename: B.h
#ifndef B_H
#define B_H
#include "A.h"
class
B{
public
:
B(){}
~B(){}
A a;
// B类中包含有A的实例
}
#endif//end B.h
//---------------------------------------------------------------
//filename: B.cpp
#include "B.h"
//其他关于B的实现,略
|
这里A类和B类中相互引用了,这样编译器在编译这两个类的时候肯定会有一个顺序,不管那个先被编译,总会出现超前引用的情形。比如A类先被编译,那么在编译A.cpp的时候就会将A.h文件完全copy进A.cpp文件,就会出现下面这种状态(其实应该是没有这步的,仅仅是为了看的清楚才写出)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//filename:A.cpp
//#include "A.h"被A.h完全替换,如下面情形
#ifndef A_H
#define A_H
//#include "B.h" 这一句是A.h中的,也同样会被替换成B.h文件的内容,如下
#ifndef B_H
#define B_H
//#include "A.h" 这一句是B.h中的,所以在Copy时候就会发现guid保护,发现宏A_H已经被定义,
class
B{
public
:
B(){}
~B(){}
A a;
// B类中包含有A的实例
}
#endif//end B.h
class
A{
public
:
A(){}
~A(){}
B b;
//A类中包含B的实例
//other codes
}
#endif //end A.h
//这里实现A类中的方法,略
//end A.cpp
|
这样在编译B.cpp时候宏B_H已经被定义,因此编译器将不会进行相应的创建B类的符号表(但是已经在之前对B类进行了编译。只是在局部的符号表中找不到B类),所以在引用B类的时候就会出现未定义,在符号表中找不到某些定义。
解决办法(直接Copy别人的^_^):
超前引用导致的错误有以下几种处理办法:
1) 使用类声明
在超前引用一个类之前,首先用一个特殊的语句说明该标识符是一个类名,即将被超前引用。其使用方法是:
a) 用class B; 声明即将超前引用的类名
b) 定义class A;
c) 定义class B;
d) 编制两个类的实现代码。
上述方法适用于所有代码在同一个文件中,一般情况下,类A和类B分别有自己的头文件和cpp文件,这种
方法需要演变成:
a) 分别定义A和B,并在cpp文件中实现之
b) 在两个头文件的开头分别用class B;和class A;声明对方
c) 在两个cpp文件中分别包含另外一个类的头文件
NOTE:这种方法切记不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。
2) 使用全局变量
由于全局变量可以避免超前引用,不用赘述。我的习惯是尽量少使用全局变量,比较混乱。
3) 使用基类指针。
这种方法是在引用超前引用类的地方一律用基类指针。而一般情况下,两个互相引用的类并不涉及其基类,因此不会造成
超前引用。
参考引用:http://www.cnblogs.com/sunnyjones/archive/2008/03/10/1099521.html