兩個類相互引用的解決方法
1 問題提出
最近在編寫“鬥地主”遊戲,在程式中有一個“CDealer”類用來實現發牌等等功能,還有一個“CPoker”類,用來表示撲克牌。在CDealer類中包含了一個CPoker類指標的成員變數,而在CPoker類中也包含了一個CDealer類指標的成員變數,如下所示:
//CPoker類標頭檔案
#pragma once
#include "Dealer.h"
class CPoker
{
public:
CPoker(void);
~CPoker(void);
private:
CDealer *m_pDealer;
};
//CDealer類的標頭檔案
#pragma
#include "Poker.h"
class CDealer
{
public:
CDealer(void);
~CDealer(void);
private:
CPoker *m_pPoker;
};
程式編譯時,錯誤提示為
poker.h(10) :error C2143: 語法錯誤: 缺少“;”(在“*”的前面)
poker.h(10) :error C4430: 缺少型別說明符- 假定為int。注意: C++ 不支援預設int
2 問題分析
因為在程式中首先包含的是Dealer.h,所以Dealer.h標頭檔案首先被編譯。如圖3-1所示。在CDealer類的標頭檔案中,第1步執行了#pragma once之後就進入到第2步,即Poker.h標頭檔案中。在Poker.h標頭檔案中進行第3步,執行#pragma once,之後進入到第4步,也就是Dealer.h中,由於Dealer.h中包含#pragma once,並且此時已經被編譯,所以第4步中的#include “Dealer.h”實際上沒有執行,繼續進行到Poker.h的第5步,定義CDealer類的指標,此時CDealer類實際上還沒有定義,因此編譯時回報錯。
3 問題解決
3.1 類的前向宣告
從2中分析可以看到,報錯的主要原因是CDealer類沒有定義。可以使用類的前向宣告(forwarddeclaration)的方式解決這個問題。如
class CDealer;
圖3-1 標頭檔案執行流程
在CPoker類定義中映入了類型別CDealer。在類宣告之後而定義之前,類CDealer是一個不完全型別(incompetetype),即已知CDealer是一個類,但不知道包含哪些成員,所以使用類的前向定義後,只能宣告該類的指標,而不是該類的物件。
同理,在Dealer.h中加入CPoker類的前向宣告。
classCPoker;
3.2 將包含標頭檔案的程式碼放到執行檔案
儘量將包含標頭檔案的語句放到執行檔案(.cpp檔案)中而不是在標頭檔案中(.h檔案)。因此,接下來將#include“Poker.h”語句放到Dealer.cpp檔案中,而將#include“Dealer.h”語句放到Poker.cpp檔案中。
4 小結
對於兩個類間相互引用引發的編譯錯誤,可以使用類前向宣告的方式解決。類前向宣告是一個不完整型別,只能使用其指標。儘量將包含標頭檔案的程式碼放在cpp執行檔案中,而不是h標頭檔案中。