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

MFC中如何定義全域性變數

轉載;來自http://blog.csdn.net/bill_ming/article/details/7407848
MFC中如何定義全域性變數

3種方法:1、在一個cpp檔案中用extern宣告,然後在其他檔案中定義就可以用
2、在**APP類中做公有變數,其他類中用AfxGetApp()得到一個App物件指標就可引用
3、專門寫一個全域性類,裡邊的變數及方法全部宣告為靜態

具體說明如下(來自網路):

最好在.cpp 中宣告,如果其它檔案用到這個變數,就用extern 就行了

1.cpp
int x ;
……

2.cpp (用到了1.cpp 的 x)
extern x;
……

這樣,你在2檔案中就可以把 X 當全域性變數來用了


如果你在.h檔案中宣告,可就不好了 (好少會在.h檔案中宣告全域性變數,你看一下 MFC 各種 .h 檔案就知了)
比如當你的 .h 檔案被兩上檔案包含:

My.h
int y ;

1.cpp
#include “My.h”

2.cpp
#include “My.h”

會出現什麼錯誤,我就不說了,自己試一試吧。


在 App 類中宣告一個公有成員
在程式其它類中可以用
AfxGetApp() 得到一個App物件指標,將它轉化成你的App類指標
然後就可以通過指標->變數使用了

如果你想自己和程式看上去”更面象物件一點”,如樓上所說在CWinApp的子類中加公有變數.

如果你不在乎什麼”面對物件”,在StdAfx.h中做外部宣告,在StdAfx.cpp中做宣告.即
StdAfx.h

extern int g_nMyGlobal;

StdAfx.cpp
int g_nMyBlobal;


一般全域性變數在使用它地cpp檔案中用:
extern int x;來宣告。當然必須在某個cpp檔案中有定義才行。

如果這些全域性變數要在多個cpp檔案種使用,可以考慮將宣告放在一個頭檔案中以方便管理:
global.h:
extern int x;

global.cpp:
int x;

a.cpp:
#include global.h

b.cpp:
#include global.h

看來你得多瞭解一下宣告,定義得區別和編譯單元得概念

總之記住:
變數的定義不要放在標頭檔案中(雖然static int x是可以的),宣告可以就行了.

變數宣告;
extern int x;

變數定義:
int x;
int x = 0;
static int x;
static int x = 0;
extern int x = 0;


用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不存在的問題。

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