1. 程式人生 > >在MFC中定義全域性變數

在MFC中定義全域性變數

           MFC中全域性變數的定義及使用

用MFC製作的工程由很多檔案構成,它不能象一般C++程式那樣隨意在類外定義全域性變數,在這裡要想定義能被工程內多個檔案共享的全域性變數和函式必須用一些特殊方法才行。實際上有多種方法可以實現,這裡只介紹兩種方法。

一、在應用程式類中定義

用MFC生成的工程中都有一個名為CxxxApp的類,它派生於CWinApp類。這個類主要進行程式的初始化,生成文件、檢視物件等工作。我們可以把需要全域性訪問的變數和函式定義為這個類的成員變數和成員函式,就可以實現全域性訪問了。

從嚴格意義上講,這種變數和函式並不是全域性的,因為它仍然只是類中的成員,只是由於我們很容易獲得CxxxApp類的指標,所以我們可以在文件、檢視、對話方塊以及各種自定義類中訪問到它們,達到與全域性變數類似的效果。訪問時用函式“AfxGetApp()”獲得CxxxApp類的指標,用“AfxGetApp()->成員”訪問變數或函式。

例:

Test.h:(應用程式類標頭檔案)

class CTestApp : public CWinApp 

public: 
int x; //全域性變數 
int f(int y); //全域性函式 
………… 
};

Test.cpp:(應用程式類程式檔案)

int CTestApp::f(int y) //全域性函式定義 

y++; 
return y; 
}

定義在CTestApp類中的變數和函式可以在其它類中被訪問。比如在檢視的某函式中要訪問變數x和函式f():

void CTestView::xyz() 

CTestApp *app = (CTestApp *)AfxGetApp(); //生成指向應用程式類的指標 
app->x = 0; //訪問變數x 
int z = app->f(1); //訪問函式f() 
………… 
}

這樣,變數x和函式f()可以視作為全域性的。

用這種方法實現的全域性變數和全域性函式雖比較簡單,但也有缺點,一是訪問不太方便,每次都需要獲取應用程式類的指標;再就是把一些與應用程式類本身無關的變數和函式放在裡面,使這個類看上去怪怪的,破壞了類的封裝。

二、用靜態變數和靜態函式實現

很喜歡API函式的那種呼叫方法,不論在哪個類中只要用“::API函式”就可以呼叫了。合理利用靜態型別(static)可以實現與此相似的全域性變數和全域性函式。

靜態變數和靜態函式有如下性質:

若在一個類中用關鍵字static宣告資料成員,則這個資料成員就只存在一個拷貝,無論該類建立了多少個例項,它始終只存在一個,即使該類的例項一個也沒建立,它也存在。

若在一個類中用關鍵字static宣告函式,該函式可以用“類名::函式名”方式訪問,無需引用該類的例項,甚至這個類的例項可以不存在。

利用這個性質實現的全域性變數和函式使用起來很方便。

值得注意的是,全域性變數和全域性函式最好集中封裝,不要在文件、檢視等類內部定義,這樣用起來才有全域性的感覺。

例:

1、新增一個沒有基類的新類,設類名起為CPublic,姑且稱之為公用類

單擊“Insert”選單下的“New Class”命令,選擇“Class type”為“Generic Class”,在“Name”欄中填入類名“CPublic”,單擊“OK”,則新類建立完畢。

2、包含公用類的標頭檔案,使各個類都能訪問它

CPublic的標頭檔案應包含在應用程式類的標頭檔案中,這樣在其它類中引用CPublic類時就不需要再包含了。

Test.h:(應用程式類標頭檔案)

#include "Public.h" //包含公用類標頭檔案

class CTestApp : public CWinApp 

………… 
};

3、在公用類中定義全域性變數和全域性函式,均使用static修飾,靜態變數還必須在類外定義和初始化

Public.h:(公用類標頭檔案)

class CPublic 

public: 
CPublic(); 
virtual ~CPublic();

public: 
static int x; //全域性變數 
static int time; //全域性變數 
static int f(int y); //全域性函式 
………… 
}

在公用類中對靜態變數進行初始化和定義函式體:

Public.cpp:(公用類程式檔案)

int CPublic::x = 0; //初始化全域性變數 
int CPublic::time; //定義全域性變數

CPublic::CPublic() 
{

}

CPublic::~CPublic() 
{

}

int CPublic::f(int y) //全域性函式,這裡不要再加static 

y++; 
return y; 
}

4、全域性量的使用

使用變數:CPublic::變數名

使用函式:CPublic::函式()

如在檢視的某函式中訪問變數x和函式f():

void CTestView::xyz() 

CPublic::x = 0; //訪問變數x 
CPublic::time = CPublic::f(1); //訪問函式f() 
………… 
}

在其它類中訪問x、time和f()的方法與此相同。

5、幾點注意:

① 由於靜態量可獨立於類存在,不需要生成CPublic類的例項。

② 靜態資料成員的定義和初始化必須在類外進行,如例中x的初始化;變數time雖然沒有初始化,但也必須在類外進行定義。由於沒有生成CPublic類的例項,所以它的建構函式和解構函式都不會被執行,在裡面做什麼工作都沒有什麼意義。

③ 如果靜態函式需要訪問CPublic類內的變數,這些變數也必須為靜態的。因為非靜態量在不生成例項時都不會存在。 如:

class CPublic 

public: 
int x; //內部變數 
static int f(int y) //全域性函式 

x++; 
return x; 
}; 
………… 
};

這裡x雖為類內成員,但如果不生成CPublic類的例項,就會出現函式f()存在,而變數x不存在的問題。

總之,用沒有例項的類管理全域性量是一個不錯的選擇,它具有集中管理,使用方便的好處。當然,除非特別必要,全域性量還是少用為好,一個好的程式設計者決不會隨意濫用全域性量的,一個封裝做得不好的程式,在修改維護時會讓你吃足苦頭

           MFC中全域性變數的定義及使用

用MFC製作的工程由很多檔案構成,它不能象一般C++程式那樣隨意在類外定義全域性變數,在這裡要想定義能被工程內多個檔案共享的全域性變數和函式必須用一些特殊方法才行。實際上有多種方法可以實現,這裡只介紹兩種方法。

一、在應用程式類中定義

用MFC生成的工程中都有一個名為CxxxApp的類,它派生於CWinApp類。這個類主要進行程式的初始化,生成文件、檢視物件等工作。我們可以把需要全域性訪問的變數和函式定義為這個類的成員變數和成員函式,就可以實現全域性訪問了。

從嚴格意義上講,這種變數和函式並不是全域性的,因為它仍然只是類中的成員,只是由於我們很容易獲得CxxxApp類的指標,所以我們可以在文件、檢視、對話方塊以及各種自定義類中訪問到它們,達到與全域性變數類似的效果。訪問時用函式“AfxGetApp()”獲得CxxxApp類的指標,用“AfxGetApp()->成員”訪問變數或函式。

例:

Test.h:(應用程式類標頭檔案)

class CTestApp : public CWinApp 

public: 
int x; //全域性變數 
int f(int y); //全域性函式 
………… 
};

Test.cpp:(應用程式類程式檔案)

int CTestApp::f(int y) //全域性函式定義 

y++; 
return y; 
}

定義在CTestApp類中的變數和函式可以在其它類中被訪問。比如在檢視的某函式中要訪問變數x和函式f():

void CTestView::xyz() 

CTestApp *app = (CTestApp *)AfxGetApp(); //生成指向應用程式類的指標 
app->x = 0; //訪問變數x 
int z = app->f(1); //訪問函式f() 
………… 
}

這樣,變數x和函式f()可以視作為全域性的。

用這種方法實現的全域性變數和全域性函式雖比較簡單,但也有缺點,一是訪問不太方便,每次都需要獲取應用程式類的指標;再就是把一些與應用程式類本身無關的變數和函式放在裡面,使這個類看上去怪怪的,破壞了類的封裝。

二、用靜態變數和靜態函式實現

很喜歡API函式的那種呼叫方法,不論在哪個類中只要用“::API函式”就可以呼叫了。合理利用靜態型別(static)可以實現與此相似的全域性變數和全域性函式。

靜態變數和靜態函式有如下性質:

若在一個類中用關鍵字static宣告資料成員,則這個資料成員就只存在一個拷貝,無論該類建立了多少個例項,它始終只存在一個,即使該類的例項一個也沒建立,它也存在。

若在一個類中用關鍵字static宣告函式,該函式可以用“類名::函式名”方式訪問,無需引用該類的例項,甚至這個類的例項可以不存在。

利用這個性質實現的全域性變數和函式使用起來很方便。

值得注意的是,全域性變數和全域性函式最好集中封裝,不要在文件、檢視等類內部定義,這樣用起來才有全域性的感覺。

例:

1、新增一個沒有基類的新類,設類名起為CPublic,姑且稱之為公用類

單擊“Insert”選單下的“New Class”命令,選擇“Class type”為“Generic Class”,在“Name”欄中填入類名“CPublic”,單擊“OK”,則新類建立完畢。

2、包含公用類的標頭檔案,使各個類都能訪問它

CPublic的標頭檔案應包含在應用程式類的標頭檔案中,這樣在其它類中引用CPublic類時就不需要再包含了。

Test.h:(應用程式類標頭檔案)

#include "Public.h" //包含公用類標頭檔案

class CTestApp : public CWinApp 

………… 
};

3、在公用類中定義全域性變數和全域性函式,均使用static修飾,靜態變數還必須在類外定義和初始化

Public.h:(公用類標頭檔案)

class CPublic 

public: 
CPublic(); 
virtual ~CPublic();

public: 
static int x; //全域性變數 
static int time; //全域性變數 
static int f(int y); //全域性函式 
………… 
}

在公用類中對靜態變數進行初始化和定義函式體:

Public.cpp:(公用類程式檔案)

int CPublic::x = 0; //初始化全域性變數 
int CPublic::time; //定義全域性變數

CPublic::CPublic() 
{

}

CPublic::~CPublic() 
{

}

int CPublic::f(int y) //全域性函式,這裡不要再加static 

y++; 
return y; 
}

4、全域性量的使用

使用變數:CPublic::變數名

使用函式:CPublic::函式()

如在檢視的某函式中訪問變數x和函式f():

void CTestView::xyz() 

CPublic::x = 0; //訪問變數x 
CPublic::time = CPublic::f(1); //訪問函式f() 
………… 
}

在其它類中訪問x、time和f()的方法與此相同。

5、幾點注意:

① 由於靜態量可獨立於類存在,不需要生成CPublic類的例項。

② 靜態資料成員的定義和初始化必須在類外進行,如例中x的初始化;變數time雖然沒有初始化,但也必須在類外進行定義。由於沒有生成CPublic類的例項,所以它的建構函式和解構函式都不會被執行,在裡面做什麼工作都沒有什麼意義。

③ 如果靜態函式需要訪問CPublic類內的變數,這些變數也必須為靜態的。因為非靜態量在不生成例項時都不會存在。 如:

class CPublic 

public: 
int x; //內部變數 
static int f(int y) //全域性函式 

x++; 
return x; 
}; 
………… 
};

這裡x雖為類內成員,但如果不生成CPublic類的例項,就會出現函式f()存在,而變數x不存在的問題。

總之,用沒有例項的類管理全域性量是一個不錯的選擇,它具有集中管理,使用方便的好處。當然,除非特別必要,全域性量還是少用為好,一個好的程式設計者決不會隨意濫用全域性量的,一個封裝做得不好的程式,在修改維護時會讓你吃足苦頭