1. 程式人生 > >關於兩個類相互包含引用的思考

關於兩個類相互包含引用的思考

今天遇到一個問題,編譯時遇到了如下錯誤:

錯誤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