關於兩個類相互包含引用的思考
今天遇到一個問題,編譯時遇到了如下錯誤:
錯誤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
這兩個類互相定義了對方的一個物件,這其實是不可能的。編譯器肯定是順序地解析,比如先解析robot.h,include了CMove的定義,此時還未開始解析CRobot的定義,但是CMove的定義卻依賴於CRobot的定義,因為在CMove中定義了CRobot的物件。這顯然不行。所以,一般來說,兩者的定義,至少有一方是使用指標,或兩者都使用指標,但是不能兩者都定義實體物件#ifndef __MOVE_H__ #define __MOVE_H__ #include "robot.h" class CMove { private: CRobot robot; }; #endif
好,接下來看下面這樣
#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