轉 C++中的static關鍵字

C++的static有兩種用法:面向過程程序設計中的static和麪向對象程序設計中的static。前者應用於普通變量和函數,不涉及類;後者主要說明static在類中的做用。
1、面向過程設計中的static
一、靜態全局變量
在全局變量前,加上關鍵字static,該變量就被定義成爲一個靜態全局變量。咱們先舉一個靜態全局變量的例子,以下:
 1 #include<iostream>  
 2 using namespace std;  
 3   
 4 static int n;  //定義靜態全局變量  
 5   
 6 void fn()  
 7 {  
 8     n++;  
 9     cout<<n<<endl;  
10 }  
11   
12 int main(void)  
13 {  
14     n = 20;  
15     cout<<n<<endl;  
16     fn();  
17     return 0;  
18 }  

 


  • 靜態全局變量有如下特色:
代碼區
全局數據區
堆區
棧區
[cpp]  static int n;  //定義靜態全局變量  
改成
[cpp]  int n;  //定義全局變量  
程序照樣正常運行。
的確,定義全局變量就能夠實現變量在文件中的共享,但定義靜態全局變量還有如下好處:
       靜態全局變量不能被其它文件所用;
       其它文件中能夠定義相同名字的變量,不會發生衝突;
您能夠將上述示例代碼改成以下:
[cpp]  //File1  
  •   
  • using namespace std;  
  • void fn();  
  • staticint//定義靜態全局變量  
  • intvoid{  
  •     cout<<n<<endl;  
  •     return 0;  
  •   
  •   
  • #include<iostream>  
  • usingnamespace  
  • externint  
  • void{  
  •     cout<<n<<endl;  
  • 編譯並運行這個程序,您就會發現上述代碼能夠分別經過編譯,但運行時出現錯誤。試着將
[cpp]  static int n;  //定義靜態全局變量  
改成
[cpp]  int n;  //定義全局變量  
再次編譯運行程序,細心體會全局變量和靜態全局變量的區別。
二、靜態局部變量
在局部變量前,加上關鍵字static,該變量就被定義成爲一個靜態局部變量。
咱們先舉一個靜態局部變量的例子,以下:
[cpp]  #include<iostream>  
  • usingnamespace  
  • void  
  • intvoid{  
  •     fn();  
  •     return 0;  
  •   
  • void{  
  • staticint    cout<<n<<endl;  
  • }  
一般,在函數體內定義了一個變量,每當程序運行到該語句時都會給該局部變量分配棧內存。但隨着程序退出函數體,系統就會收回棧內存,局部變量也相應失效。
  但有時候咱們須要在兩次調用之間對變量的值進行保存。一般的想法是定義一個全局變量來實現。但這樣一來,變量已經再也不屬於函數自己了,再也不僅受函數的控制,給程序的維護帶來不便。
  靜態局部變量正好能夠解決這個問題。靜態局部變量保存在全局數據區,而不是保存在棧中,每次的值保持到下一次調用,直到下次賦新值。
靜態局部變量有如下特色:
    (1)該變量在全局數據區分配內存;
    (2)靜態局部變量在程序執行到該對象的聲明處時被首次初始化,即之後的函數調用再也不進行初始化;
    (3)靜態局部變量通常在聲明處初始化,若是沒有顯式初始化,會被程序自動初始化爲0;
    (4)它始終駐留在全局數據區,直到程序運行結束。但其做用域爲局部做用域,當定義它的函數或語句塊結束時,其做用域隨之結束;
三、靜態函數
  在函數的返回類型前加上static關鍵字,函數即被定義爲靜態函數。靜態函數與普通函數不一樣,它只能在聲明它的文件當中可見,不能被其它文件使用。
靜態函數的例子:
[cpp]  #include<iostream>  
  • usingnamespace  
  • staticvoid//聲明靜態函數  
  • intvoid{  
  •     return 0;  
  •   
  • void//定義靜態函數{  
  • int    cout<<n<<endl;  
  • 定義靜態函數的好處:
[cpp]  #include<iostream>  
  • usingnamespace  
  • class{  
  • private    int a , b , c;  
  • staticint//聲明靜態數據成員public:  
  • intintint    void GetSum();  
  •   
  • int//定義並初始化靜態數據成員  
  • intintint{  
  • this    this->b = b;  
  • this    sum += a+b+c;  
  • void Myclass::GetSum()  
  •     cout<<"sum="<<sum<<endl;  
  •   
  • intvoid{  
  •     M.GetSum();  
  •     N.GetSum();  
  •     return 0;  
  • 能夠看出,靜態數據成員有如下特色:
  1. 靜態數據成員沒有進入程序的全局名字空間,所以不存在與程序中其它全局名字衝突的可能性;
  2. 能夠實現信息隱藏。靜態數據成員能夠是private成員,而全局變量不能;
  與靜態數據成員同樣,咱們也能夠建立一個靜態成員函數,它爲類的所有服務而不是爲某一個類的具體對象服務。靜態成員函數與靜態數據成員同樣,都是類的內部實現,屬於類定義的一部分。普通的成員函數通常都隱含了一個this指針,this指針指向類的對象自己,由於普通成員函數老是具體的屬於某個類的具體對象的。一般狀況下,this是缺省的。如函數fn()其實是this->fn()。可是與普通函數相比,靜態成員函數因爲不是與任何的對象相聯繫,所以它不具備this指針。從這個意義上講,它沒法訪問屬於類對象的非靜態數據成員,也沒法訪問非靜態成員函數,它只能調用其他的靜態成員函數。下面舉個靜態成員函數的例子。
[cpp]  #include<iostream>  
  • usingnamespace  
  • class{  
  • private    int a , b , c;  
  • staticint//聲明靜態數據成員public:  
  • intintint    static void GetSum();  //聲明靜態成員函數  
  •   
  • int//定義並初始化靜態數據成員  
  • intintint{  
  • this    this->b = b;  
  • this    sum += a+b+c;    //非靜態成員函數能夠訪問靜態數據成員  
  • void Myclass::GetSum()    //靜態成員函數的實現  
  •     //cout<<a<<endl;    //錯誤代碼,a是非靜態數據成員  
  • "sum="}  
  • int main(void)  
  •     Myclass M(1 , 2 , 3);  
  •     Myclass N(4 , 5 , 6);  
  •     Myclass::GetSum();  
  • return}  
關於靜態成員函數,能夠總結爲如下幾點:
  • 出如今類體外的函數定義不能指定關鍵字static;
  • 靜態成員之間能夠相互訪問,包括靜態成員函數訪問靜態數據成員和訪問靜態成員函數;
  • 非靜態成員函數能夠任意地訪問靜態成員函數和靜態數據成員;
  • 靜態成員函數不能訪問非靜態成員函數和非靜態數據成員;
  • 因爲沒有this指針的額外開銷,所以靜態成員函數與類的全局函數相比速度上會有少量的增加;
  • 調用靜態成員函數,能夠用成員訪問操做符(.)和(->)爲一個類的對象或指向類對象的指針調用靜態成員函數,也能夠直接使用以下格式:
<類名>::<靜態成員函數名>(<參數表>)
調用類的靜態成員函數。
相關文章
相關標籤/搜索