所謂超前引用是指乙個型別在定義之前就被用來定義變數和宣告函式。
一般情況下,c/c++要求所有的型別必須在使用前被定義,但是在一些特殊情況下,這種要求無法滿足,例如,在類cmyview中保留了乙個非模式對話方塊物件指標,該物件用於顯示/修改一些資訊。為了實現對話方塊"應用"按鈕,把對話方塊做的修改立刻更新到view介面上,為此,需要在對話方塊類中需要儲存view類的指標,這樣定義關係就變成如下的**:
#ifndef __myview_h__
#define __myview_h__
//這是view類的頭函式
#include "mydialog.h"
class cmyview::public cview
;#endif
#ifndef __mydialog_h__
#define __mydialog_h__
//這是對話方塊類的定義
#include "myview.h"
class cmydialog::public cdialog
;#endif
從編譯器角度看,編譯mydialog.cpp時,系統首先定義巨集__mydialog_h__,然後包含myview.h,myview.h中的#include "mydialog.h"由於__mydialog_h__已經定義,所以不再起作用。在cmyview類的宣告中,cmydialog* pdlg ;就會讓編譯器產生"cmydialog"型別沒有定義之類的錯誤,編譯myview.cpp檔案出現的錯誤可以類似得到。
更一般的情況,類a和類b需要彼此互相引用,這樣必然有乙個類會先被定義,而另外乙個類後被定義,這樣在先被定義的類引用後被定義的類的時候,就導致了所謂的超前引用。
超前引用導致的錯誤有以下幾種處理辦法:
1) 使用類宣告
在超前引用乙個類之前,首先用乙個特殊的語句說明該識別符號是乙個類名,即將被超前引用。其使用方法是:
a) 用class classb;宣告即將超前引用的類名
b) 定義class classa
c) 定義class classb;
d) 編制兩個類的實現**。
上述方法適用於所有**在同乙個檔案中,一般情況下,classa和classb分別有自己的標頭檔案和cpp檔案,這種
方法需要演變成:
a) 分別定義classa和classb,並在cpp檔案中實現之
b) 在兩個標頭檔案的開頭分別用class classb;和class classa;宣告對方
c) 在兩個cpp檔案中分別包含另外乙個類的標頭檔案
note:這種方法切記不可使用類名來定義變數和函式的變數引數,只可用來定義引用或者指標。
2) 使用全域性變數
由於全域性變數可以避免超前引用,不用贅述。我的習慣是,把類物件的extern語句加在該類標頭檔案的最後,大家喜歡
怎樣寫那都沒有什麼大問題,關鍵是保證不要在標頭檔案中胡亂包含。
3) 使用基類指標。
這種方法是在引用超前引用類的地方一律用基類指標。而一般情況下,兩個互相引用的類並不涉及其基類,因此不會造成
超前引用。以開始的例子說:在cmydialog類中用cview*代替cmyview*,在cmyview類中用cdialog*代替cmydialog*,這樣必然
不會造成超前引用。
說明:本文中,為了敘述方便,把class aclass;語句成為類aclass的宣告,把class aclass開始的對aclass的類成員變數、
成員函式原型等的說明稱為類的定義,而把在cpp中的部分稱為類的定義。如果大家對這三個詞有不同的理解,請按照自己的本意
把這三個詞換成相應的詞來理解。
解決標頭檔案相互包含問題的方法
所謂超前引用是指乙個型別在定義之前就被用來定義變數和宣告函式。一般情況下,c c 要求所有的型別必須在使用前被定義,但是在一些特殊情況下,這種要求無法滿足,例如,在類cmyview中保留了乙個非模式對話方塊物件指標,該物件用於顯示 修改一些資訊。為了實現對話方塊 應用 按鈕,把對話方塊做的修改立刻更...
解決標頭檔案相互包含問題的方法
所謂超前引用是指乙個型別在定義之前就被用來定義變數和宣告函式。一般情況下,c c 要求所有的型別必須在使用前被定義,但是在一些特殊情況下,這種要求無法滿足,例如,在類 cmyview 中保留了乙個非模式對話方塊物件指標,該物件用於顯示 修改一些資訊。為了實現對話方塊 應用 按鈕,把對話方塊做的修改立...
c 標頭檔案相互包含問題
c 中標頭檔案互相包含經常會出現編譯錯誤.示例 如下 h ifndef a h define a h include b.h includeusing namespace std class a endif a h a.cpp include a.h a a a a int a getvala vo...