诡异的未定义错误--超前引用

从自己的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已经被定义,

//所以到这里终止,因此这里就终止了A.h的copy

  
  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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值