关于两个类相互包含引用的思考

今天遇到一个问题,编译时遇到了如下错误:

错误 1 error C2146: 语法错误: 缺少“;”(在标识符“move”的前面)

错误 2 error C4430: 缺少类型说明符 - 假定为 int。注意:  C++ 不支持默认 int


写个最简单的例子:

#ifndef __ROBOT_H__
#define __ROBOT_H__
#include "move.h"

class CRobot
{
private:
	CMove move;
};

#endif

#ifndef __MOVE_H__
#define __MOVE_H__

#include "robot.h"

class CMove
{
private:
	CRobot robot;
};

#endif
这两个类互相定义了对方的一个对象,这其实是不可能的。编译器肯定是顺序地解析,比如先解析robot.h,include了CMove的定义,此时还未开始解析CRobot的定义,但是CMove的定义却依赖于CRobot的定义,因为在CMove中定义了CRobot的对象。这显然不行。所以,一般来说,两者的定义,至少有一方是使用指针,或两者都使用指针,但是不能两者都定义实体对象


好,接下来看下面这样

#ifndef __ROBOT_H__
#define __ROBOT_H__
#include "move.h"
class CRobot
{
private:
CMove move;
};
#endif


#ifndef __MOVE_H__
#define __MOVE_H__
#include "robot.h"
class CMove
{
private:
	CRobot *robot;
};
#endif


那么这样行不行呢?  答案是编译器仍然报错
在编译CRobot时,include了move.h,其实就是拷贝,由于#ifndef的效果,robot.h不会被二次包含,所以相当于下面这样
class CMove
{
private:
CRobot *robot;
};

class CRobot
{
private:
CMove move;
};

这个时候对于CMove来说,CRobot仍然是不可见的,因为其定义在后面,所以其实需要一个CRobot的一个前向声明。
注:声明的类类型可以用来定义指针或引用,但是不能定义对象,因为仅仅是声明,在编译器看来,指针和引用的大小是确定的。但是定义对象就需要知道确切的类定义,这样编译器才能知道类大小(编译器需要在编译期知道对象所占空间大小)
所以在CRobot中还是需要include CMove类,需要知道其定义




但是对于CMove来说,其仅仅需要知道CRobot的声明,不需要include其头文件,只需要一个前向声明。但是我在VS 2013上试了一下,加一个前向声明再include robot.h,这样也是通不过编译的,不知道为什么??????
#ifndef __MOVE_H__
#define __MOVE_H__
class CRobot;


#include "robot.h"
class CMove
{
private:
CRobot *robot;
};
#endif

一般的做法是:两个类的头文件之中,选一个包含另一个类的头文件,但另一个头文件中只能采用class *的声明形式,自然只能定义指针或者引用,而在实现文件中(*.cpp)中包含头文件。当然,用类定义对象的文件一定得包含头文件



可以参考下以下博客:
http://www.jianshu.com/p/51ceab77f903
http://blog.csdn.net/yang_lang/article/details/6767439
http://blog.csdn.net/hazir/article/details/38600419
http://blog.csdn.net/zyrr159487/article/details/6932229
http://www.cnblogs.com/zendu/p/4987971.html


你可能感兴趣的:(C++)