所謂超前引用是指一個類型在定義之前就被用來定義變量和聲明函數。
一般情況下,C/C++要求所有的類型必須在使用前被定義,但是在一些特殊情況下,這種要求無法滿足,例如,在類CMyView中保留了一個非模式對話框對象指針,該對象用於顯示/修改一些信息。爲了實現對話框"應用"按鈕,把對話框做的修改立刻更新到view界面上,爲此,需要在對話框類中需要保存view類的指針,這樣定義關係就變成如下的代碼:
#ifndef __MYVIEW_H__
#define __MYVIEW_H__
//這是view類的頭函數
#include "MyDialog.h"
class CMyView::public CView
{
protected:
CMyDialog * pDlg;
//這裏是其他定義
};
#endif
#ifndef __MYDIALOG_H__
#define __MYDIALOG_H__
//這是對話框類的定義
#include "MyView.h"
class CMyDialog::public CDialog
{
protected:
CMyView * pView;
//其他定義
};
#endif
#define __MYVIEW_H__
//這是view類的頭函數
#include "MyDialog.h"
class CMyView::public CView
{
protected:
CMyDialog * pDlg;
//這裏是其他定義
};
#endif
#ifndef __MYDIALOG_H__
#define __MYDIALOG_H__
//這是對話框類的定義
#include "MyView.h"
class CMyDialog::public CDialog
{
protected:
CMyView * pView;
//其他定義
};
#endif
從編譯器角度看,編譯MyDialog.CPP時,系統首先定義宏__MYDIALOG_H__,然後包含MyView.h,MyView.h中的#include "MyDialog.h"由於__MYDIALOG_H__已經定義,所以不再起作用。在CMyView類的聲明中,CMyDialog* pDlg ;就會讓編譯器產生"CMyDialog"類型沒有定義之類的錯誤,編譯MyView.CPP文件出現的錯誤可以類似得到。
更一般的情況,類A和類B需要彼此互相引用,這樣必然有一個類會先被定義,而另外一個類後被定義,這樣在先被定義的類引用後被定義的類的時候,就導致了所謂的超前引用。
更一般的情況,類A和類B需要彼此互相引用,這樣必然有一個類會先被定義,而另外一個類後被定義,這樣在先被定義的類引用後被定義的類的時候,就導致了所謂的超前引用。
超前引用導致的錯誤有以下幾種處理辦法:
1) 使用類聲明
在超前引用一個類之前,首先用一個特殊的語句說明該標識符是一個類名,即將被超前引用。其使用方法是:
a) 用class B; 聲明即將超前引用的類名
b) 定義class A;
c) 定義class B;
d) 編制兩個類的實現代碼。
上述方法適用於所有代碼在同一個文件中,一般情況下,類A和類B分別有自己的頭文件和cpp文件,這種
方法需要演變成:
a) 分別定義A和B,並在cpp文件中實現之
b) 在兩個頭文件的開頭分別用class B;和class A;聲明對方
c) 在兩個cpp文件中分別包含另外一個類的頭文件
NOTE:這種方法切記不可使用類名來定義變量和函數的變量參數,只可用來定義引用或者指針。
2) 使用全局變量
由於全局變量可以避免超前引用,不用贅述。我的習慣是儘量少使用全局變量,比較混亂。
1) 使用類聲明
在超前引用一個類之前,首先用一個特殊的語句說明該標識符是一個類名,即將被超前引用。其使用方法是:
a) 用class B; 聲明即將超前引用的類名
b) 定義class A;
c) 定義class B;
d) 編制兩個類的實現代碼。
上述方法適用於所有代碼在同一個文件中,一般情況下,類A和類B分別有自己的頭文件和cpp文件,這種
方法需要演變成:
a) 分別定義A和B,並在cpp文件中實現之
b) 在兩個頭文件的開頭分別用class B;和class A;聲明對方
c) 在兩個cpp文件中分別包含另外一個類的頭文件
NOTE:這種方法切記不可使用類名來定義變量和函數的變量參數,只可用來定義引用或者指針。
2) 使用全局變量
由於全局變量可以避免超前引用,不用贅述。我的習慣是儘量少使用全局變量,比較混亂。
3) 使用基類指針。
這種方法是在引用超前引用類的地方一律用基類指針。而一般情況下,兩個互相引用的類並不涉及其基類,因此不會造成
超前引用。以開始的例子說:在CMyDialog類中用CView*代替CMyView*,在CMyView類中用CDialog*代替CMyDialog*,這樣必然
不會造成超前引用。
這種方法是在引用超前引用類的地方一律用基類指針。而一般情況下,兩個互相引用的類並不涉及其基類,因此不會造成
超前引用。以開始的例子說:在CMyDialog類中用CView*代替CMyView*,在CMyView類中用CDialog*代替CMyDialog*,這樣必然
不會造成超前引用。