這篇介紹了靜態(tài)成員函數(shù)與靜態(tài)成員變量,是我的讀書筆記,我希望它夠簡短但又比較全面,起到復(fù)習(xí)的作用。如果有一些C++知識記不清楚了,它可以幫你很快回憶起來。

復(fù)習(xí)C語言的static關(guān)鍵字

(1)加在局部變量的前面使之成為靜態(tài)局部變量,作用域還是在函數(shù)內(nèi)部,可是生存周期延長了。

(2)加在全局變量的前面限定該變量作用域為文件作用域,就是說即使其他文件使用了extern擴(kuò)展作用域也不行。這在C語言的多人項目中非常有用,避免了變量的重名。然而在C++中這一功能已經(jīng)被命名空間取代,但是為了保持和C語言的兼容,static還是有這樣的功能。

(3)加在函數(shù)定義或聲明的前面,限定函數(shù)作用域到文件作用域,也是為了避免多個文件中有重名函數(shù)。

當(dāng)static關(guān)鍵字出現(xiàn)在類中

當(dāng)static出現(xiàn)在類的定義中便出現(xiàn)了靜態(tài)成員變量和靜態(tài)成員函數(shù)。靜態(tài)成員是屬于類的,而不是屬于某個對象的。即便沒有任何一個實例,類的靜態(tài)成員變量也已經(jīng)存在了,而且還可能通過“類名::成員名”進(jìn)行訪問。類的靜態(tài)成員函數(shù)也可以用相同的方式調(diào)用,在類產(chǎn)生實例之前就調(diào)用成員方法,典型應(yīng)用是實現(xiàn)單例模式。

(1)靜態(tài)成員變量

靜態(tài)成員變量本質(zhì)上是全局變量,但是將和某些類關(guān)系緊密的全局變量寫到類里面,形式上成為一個整體,更容易理解和維護(hù)。所以盡量使用靜態(tài)成員變量吧,減少全局變量的使用。普通成員變量每個對象都有各自的一份,但是靜態(tài)成員變量一共只有一份,被所有的本類對象共享。如果使用sizeof運(yùn)算符計算對象的大小,得到的結(jié)果是不包含靜態(tài)成員變量在內(nèi)的。

靜態(tài)成員同樣受到private,public等的限制。

靜態(tài)成員變量的一個典型應(yīng)用就是用來計數(shù)生成的實例的個數(shù)。大體思路是設(shè)置一個名為num的靜態(tài)成員變量并初始化為0,在構(gòu)造函數(shù)中++num,析構(gòu)函數(shù)中--num。這樣num的值就是當(dāng)前實例的個數(shù)。實際上這也帶來了一個隱蔽的bug??聪旅娴拇a:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 1 class CNum { 2      public: 3              static int num; 4              ~CNum() { --num; } 5              CNum() { ++num; } 6 }; 7  8 int CNum::num = 0; 9 void fun(CNum n){ }10 11  int main() {12      CNum n;13      fun(n);14      fun(n);15      cout << CNum::num << endl;16     return 0;17 }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

結(jié)果:-1

num盡然成了一個負(fù)數(shù),難道析構(gòu)函數(shù)比構(gòu)造函數(shù)多調(diào)用了一次?實際上不是的。當(dāng)執(zhí)行 fun(n); 語句時調(diào)用了復(fù)制構(gòu)造函數(shù),這個函數(shù)因為我們沒有給出實現(xiàn),所以是用的編譯器默認(rèn)提供的版本,在這個構(gòu)造函數(shù)中并沒有++num這條語句,因此少計數(shù)了兩次(兩次調(diào)用fun(n))。

解決的方法就是一定要提供自己寫的復(fù)制構(gòu)造函數(shù)并在函數(shù)體中加入 ++num; 

(2)靜態(tài)成員函數(shù)

靜態(tài)成員函數(shù)內(nèi)部不能調(diào)用非靜態(tài)成員函數(shù),原因是,非靜態(tài)成員函數(shù)需要傳入一個this指針,這讓靜態(tài)成員函數(shù)很為難,它并不知道與之相關(guān)的信息,也就無法提供this指針。

靜態(tài)成員變量的初始化

上面代碼中的第8行  int CNum::num = 0; 是靜態(tài)成員變量的初始化。這可以視為是靜態(tài)變量的定義(定義的同時初始化,即便不初始化也需要這個定義),而把類內(nèi)的 static int num; 視為一個聲明,這樣的理解可以突出這樣一個事實:靜態(tài)成員變量本質(zhì)上是全局變量。注意在類外定義時加上“類名::”。

對于常量成員變量,我們知道初始化時一定要使用初始化列表,那么當(dāng)一個變量既是常量又是靜態(tài)成員時(同時被const和static修飾)要怎么樣初始化呢?是像一般的靜態(tài)成員變量一樣在類外定義并初始化,還是像一般的常量成員變量一樣使用初始化列表呢?答案時前者,即在類外定義并初始化,在類內(nèi)聲明,就像下面那樣:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 1 class CNum { 2      public: 3             const static int num; 4 }; 5  6 const int CNum::num = 0; 7  8  int main() { 9      CNum n;10     return 0;11 }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

實際上,完全可以把const int 視為一種數(shù)據(jù)類型,它的地位和int一樣。這樣理解是有好處的,比如從const int到int需要強(qiáng)制類型轉(zhuǎn)換,把他們看成兩種類型,這就自然而然。相應(yīng)的const char 和char 也應(yīng)該看成兩種類型,就好像它們完全沒有什么特殊的關(guān)系一樣。

另外static const int類型和static const char 類型可以在類內(nèi)直接初始化,就是說都不需要在類外再次定義,像下面這樣:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 1 class CNum { 2      public: 3          const static int a = 19; 4 }; 5  6  7  int main() { 8      cout << CNum::a  << endl;    //輸出19 9     return 0;10 }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

這篇介紹了靜態(tài)成員函數(shù)與靜態(tài)成員變量,是我的讀書筆記,我希望它夠簡短但又比較全面,起到復(fù)習(xí)的作用。如果有一些C++知識記不清楚了,它可以幫你很快回憶起來。

復(fù)習(xí)C語言的static關(guān)鍵字

(1)加在局部變量的前面使之成為靜態(tài)局部變量,作用域還是在函數(shù)內(nèi)部,可是生存周期延長了。

(2)加在全局變量的前面限定該變量作用域為文件作用域,就是說即使其他文件使用了extern擴(kuò)展作用域也不行。這在C語言的多人項目中非常有用,避免了變量的重名。然而在C++中這一功能已經(jīng)被命名空間取代,但是為了保持和C語言的兼容,static還是有這樣的功能。

(3)加在函數(shù)定義或聲明的前面,限定函數(shù)作用域到文件作用域,也是為了避免多個文件中有重名函數(shù)。

當(dāng)static關(guān)鍵字出現(xiàn)在類中

當(dāng)static出現(xiàn)在類的定義中便出現(xiàn)了靜態(tài)成員變量和靜態(tài)成員函數(shù)。靜態(tài)成員是屬于類的,而不是屬于某個對象的。即便沒有任何一個實例,類的靜態(tài)成員變量也已經(jīng)存在了,而且還可能通過“類名::成員名”進(jìn)行訪問。類的靜態(tài)成員函數(shù)也可以用相同的方式調(diào)用,在類產(chǎn)生實例之前就調(diào)用成員方法,典型應(yīng)用是實現(xiàn)單例模式。

(1)靜態(tài)成員變量

靜態(tài)成員變量本質(zhì)上是全局變量,但是將和某些類關(guān)系緊密的全局變量寫到類里面,形式上成為一個整體,更容易理解和維護(hù)。所以盡量使用靜態(tài)成員變量吧,減少全局變量的使用。普通成員變量每個對象都有各自的一份,但是靜態(tài)成員變量一共只有一份,被所有的本類對象共享。如果使用sizeof運(yùn)算符計算對象的大小,得到的結(jié)果是不包含靜態(tài)成員變量在內(nèi)的。

靜態(tài)成員同樣受到private,public等的限制。

靜態(tài)成員變量的一個典型應(yīng)用就是用來計數(shù)生成的實例的個數(shù)。大體思路是設(shè)置一個名為num的靜態(tài)成員變量并初始化為0,在構(gòu)造函數(shù)中++num,析構(gòu)函數(shù)中--num。這樣num的值就是當(dāng)前實例的個數(shù)。實際上這也帶來了一個隱蔽的bug??聪旅娴拇a:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 1 class CNum { 2      public: 3              static int num; 4              ~CNum() { --num; } 5              CNum() { ++num; } 6 }; 7  8 int CNum::num = 0; 9 void fun(CNum n){ }10 11  int main() {12      CNum n;13      fun(n);14      fun(n);15      cout << CNum::num << endl;16     return 0;17 }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

結(jié)果:-1

num盡然成了一個負(fù)數(shù),難道析構(gòu)函數(shù)比構(gòu)造函數(shù)多調(diào)用了一次?實際上不是的。當(dāng)執(zhí)行 fun(n); 語句時調(diào)用了復(fù)制構(gòu)造函數(shù),這個函數(shù)因為我們沒有給出實現(xiàn),所以是用的編譯器默認(rèn)提供的版本,在這個構(gòu)造函數(shù)中并沒有++num這條語句,因此少計數(shù)了兩次(兩次調(diào)用fun(n))。

解決的方法就是一定要提供自己寫的復(fù)制構(gòu)造函數(shù)并在函數(shù)體中加入 ++num; 

(2)靜態(tài)成員函數(shù)

靜態(tài)成員函數(shù)內(nèi)部不能調(diào)用非靜態(tài)成員函數(shù),原因是,非靜態(tài)成員函數(shù)需要傳入一個this指針,這讓靜態(tài)成員函數(shù)很為難,它并不知道與之相關(guān)的信息,也就無法提供this指針。

靜態(tài)成員變量的初始化

上面代碼中的第8行  int CNum::num = 0; 是靜態(tài)成員變量的初始化。這可以視為是靜態(tài)變量的定義(定義的同時初始化,即便不初始化也需要這個定義),而把類內(nèi)的 static int num; 視為一個聲明,這樣的理解可以突出這樣一個事實:靜態(tài)成員變量本質(zhì)上是全局變量。注意在類外定義時加上“類名::”。

對于常量成員變量,我們知道初始化時一定要使用初始化列表,那么當(dāng)一個變量既是常量又是靜態(tài)成員時(同時被const和static修飾)要怎么樣初始化呢?是像一般的靜態(tài)成員變量一樣在類外定義并初始化,還是像一般的常量成員變量一樣使用初始化列表呢?答案時前者,即在類外定義并初始化,在類內(nèi)聲明,就像下面那樣:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 1 class CNum { 2      public: 3             const static int num; 4 }; 5  6 const int CNum::num = 0; 7  8  int main() { 9      CNum n;10     return 0;11 }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

實際上,完全可以把const int 視為一種數(shù)據(jù)類型,它的地位和int一樣。這樣理解是有好處的,比如從const int到int需要強(qiáng)制類型轉(zhuǎn)換,把他們看成兩種類型,這就自然而然。相應(yīng)的const char 和char 也應(yīng)該看成兩種類型,就好像它們完全沒有什么特殊的關(guān)系一樣。

另外static const int類型和static const char 類型可以在類內(nèi)直接初始化,就是說都不需要在類外再次定義,像下面這樣:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 1 class CNum { 2      public: 3          const static int a = 19; 4 }; 5  6  7  int main() { 8      cout << CNum::a  << endl;    //輸出19 9     return 0;10 }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

http://www.cnblogs.com/painterQ/p/7009404.html