C++中局部變量有三種:
(1)auto:此關鍵詞常常省略。auto type a 常常簡寫爲type a。
如:
int a=auto int a
存儲在內存的棧中,只在此局部區域有定義,程序執行過此局部區域自動釋放。
(2)static:有以下特點:
(1)聲明在局部區域,第一次執行時定義,以後就不再定義;
(2)同auto和register,只在其定義的局部區域有定義;
(3)區別與auto和register,static局部變量存儲在內存的靜態變量區。所以下次執行到此局部區域時,上次的結果值得以保留。
例:
int get() { static int a=0; return a++; } int main() { cout<<get()<<get(); return 0; }
程序輸出:01。第二次不再執行static變量a的定義。
(3)register:基本同auto,只是直接存儲在CPU的寄存器組。
2用於全局變量和全局函數
你可能會問?用在局部就存儲在內存的靜態變量區了,那麼定義到全局又有什麼作用呢?
這種定義常用於有多個文檔的工程的變量/函數保護。舉個栗子:
static int a, static void fun();
上面定義了一個全局static變量a,一個static函數fun。
加上static可以保證其它文檔不可以訪問到他們。回想一下,怎樣讓一個變量在多個文檔中都可以使用?extern!對的。
Talk is cheap, I will show you the code:
/*FileName: File1.cpp */ int a; /*FileName: File2.cpp*/ extern int a;
在File1.cpp中定義了int a,只需在File2.cpp中extern一下,便可以把File1.cpp中的變量a直接拿來用,他們是同一個變量。
那麼,如果File1.cpp中,我們把a的定義換爲static int a,那麼在File2.cpp中extern int a會發生什麼呢?肯定報錯啦,我剛剛都說過了,static定義在全局,可以起到保護作用,保證此定義只能被本文檔使用。
函數的情況也是一樣的。
3用於成員變量
class A { public: static int a; };
a便成爲了A的靜態成員變量。
(1)它只屬於A,不屬於A的任何一個對象。
(2)它不能被A的構造函數初始化,需要單獨定義、初始化,其方法和類成員函數的定義相同。
(3)兩種訪問方法:
1)通過類A::a; 2)通過類對象/指針:obj_A.a,ptr_A->a。
例子:
class A { public: static int a; }; int A::a = 100 ;
int _tmain(int argc, _TCHAR* argv[]) { A obj_A; A *ptr_A=&obj_A; cout << A::a << " " << obj_A.a << " " << ptr_A->a << endl; while (1); return 0; }
4用於成員函數
成員函數有了static的修飾便成了靜態成員函數,它的基本屬性與靜態成員變量一致。另外,由於虛函數要在對象中創建虛表,所以虛函數無法爲static函數。
小總結:不能爲虛的幾種函數:普通函數、友元函數、構造函數、靜態成員函數、內聯函數。
靜態成員函數最大的特點是它沒有this指針,它的其它特性都因此而來。如果對一個靜態成員函數求指針,得到的將不是一個指向member function函數的指針,而是指向普通function的指針。例如
有classA一個函數static void fun();&classA::fun()會得到void(*)(),而不是void(classA::*)()。也就是說,static最大程序上近似於非成員函數。這種特性提供了一個意想不到的好處:static成員函數可以作爲callback函數!
C++把靜態成員函數稱作類方法,把其他成員函數稱作實例方法。不同之處:
(1)類方法只有一份實例,不屬於任何一個對象。
(2)類方法只能調用類方法,不能調用實例方法。而實例方法可以調用類方法。
(3)類方法不能調用非靜態成員變量
最後一個栗子:
class cA { public: int objVar1; static int classVar1; static void classFun1() { classVar1 = 0; objVar1 = 0;//錯誤!!!類方法無法訪問非靜態成員函數 classFun2(); objFun1();//錯誤!!!類方法無法調用實例方法 }; static void classFun2(){}; void objFun1() { classVar1 = 0; objVar1 = 0; classFun1(); objFun2(); }; void objFun2(){}; };