c++的static有兩種用法:面向過程程式設計中的static和物件導向程式設計中的static。前者應用於普通變數和函式,不涉及類;後者主要說明static在類中的作用。
1.面向過程設計中的static
1.1靜態全域性變數
在全域性變數前,加上關鍵字static,該變數就被定義成為乙個靜態全域性變數。我們先舉乙個靜態全域性變數的例子,如下:
//example 1
#include
void fn();
static int n; //定義靜態全域性變數
void main()
void fn()
void fn()//定義靜態函式
;int myclass::sum=0;//定義並初始化靜態資料成員
myclass::myclass(int a,int b,int c)
void myclass::getsum()
可以看出,靜態資料成員有以下特點:
• 對於非靜態資料成員,每個類物件都有自己的拷貝。而靜態資料成員被當作是類的成員。無論這個類的物件被定義了多少個,靜態資料成員在程式中也只有乙份拷貝,由該型別的所有物件共享訪問。也就是說,靜態資料成員是該類的所有物件所共有的。對該類的多個物件來說,靜態資料成員只分配一次記憶體,供所有物件共用。所以,靜態資料成員的值對每個物件都是一樣的,它的值可以更新;
• 靜態資料成員儲存在全域性資料區。靜態資料成員定義時要分配空間,所以不能在類宣告中定義。在example 5中,語句int myclass::sum=0;是定義靜態資料成員;
• 靜態資料成員和普通資料成員一樣遵從public,protected,private訪問規則;
• 因為靜態資料成員在全域性資料區分配記憶體,屬於本類的所有物件共享,所以,它不屬於特定的類物件,在沒有產生類物件時其作用域就可見,即在沒有產生類的例項時,我們就可以操作它;
• 靜態資料成員初始化與一般資料成員初始化不同。靜態資料成員初始化的格式為:
<資料型別><類名>::<靜態資料成員名>=<值>
• 類的靜態資料成員有兩種訪問形式:
<類物件名>.<靜態資料成員名> 或 <類型別名>::<靜態資料成員名>
如果靜態資料成員的訪問許可權允許的話(即public的成員),可在程式中,按上述格式來引用靜態資料成員 ;
• 靜態資料成員主要用在各個物件都有相同的某項屬性的時候。比如對於乙個存款類,每個例項的利息都是相同的。所以,應該把利息設為存款類的靜態資料成員。這有兩個好處,第一,不管定義多少個存款類物件,利息資料成員都共享分配在全域性資料區的記憶體,所以節省儲存空間。第二,一旦利息需要改變時,只要改變一次,則所有存款類物件的利息全改變過來了;
• 同全域性變數相比,使用靜態資料成員有兩個優勢:
1. 靜態資料成員沒有進入程式的全域性名字空間,因此不存在與程式中其它全域性名字衝突的可能性;
2. 可以實現資訊隱藏。靜態資料成員可以是private成員,而全域性變數不能;
2.2靜態成員函式
與靜態資料成員一樣,我們也可以建立乙個靜態成員函式,它為類的全部服務而不是為某乙個類的具體物件服務。靜態成員函式與靜態資料成員一樣,都是類的內部實現,屬於類定義的一部分。普通的成員函式一般都隱含了乙個this指標,this指標指向類的物件本身,因為普通成員函式總是具體的屬於某個類的具體物件的。通常情況下,this是預設的。如函式fn()實際上是this->fn()。但是與普通函式相比,靜態成員函式由於不是與任何的物件相聯絡,因此它不具有this指標。從這個意義上講,它無法訪問屬於類物件的非靜態資料成員,也無法訪問非靜態成員函式,它只能呼叫其餘的靜態成員函式。下面舉個靜態成員函式的例子。
//example 6
#include
class myclass
;int myclass::sum=0;//定義並初始化靜態資料成員
myclass::myclass(int a,int b,int c)
void myclass::getsum() //靜態成員函式的實現
關於靜態成員函式,可以總結為以下幾點:
• 出現在類體外的函式定義不能指定關鍵字static;
• 靜態成員之間可以相互訪問,包括靜態成員函式訪問靜態資料成員和訪問靜態成員函式;
• 非靜態成員函式可以任意地訪問靜態成員函式和靜態資料成員;
• 靜態成員函式不能訪問非靜態成員函式和非靜態資料成員;
• 由於沒有this指標的額外開銷,因此靜態成員函式與類的全域性函式相比速度上會有少許的增長;
• 呼叫靜態成員函式,可以用成員訪問操作符(.)和(->)為乙個類的物件或指向類物件的指標呼叫靜態成員函式,也可以直接使用如下格式:
<類名>::<靜態成員函式名>(<參數列>)
呼叫類的靜態成員函式。
static主要有三個作用:
(1)區域性靜態變數
(2)外部靜態變數/函式
(3)靜態資料成員/成員函式
前兩種c和c++都有,第三種僅在c++中有,下面分別作以下介紹:
一、區域性靜態變數
在c/c++中, 區域性變數按照儲存形式可分為三種auto, static, register。其中register不常用到,下面主要說說auto和static的區別。
1. 儲存空間分配和生存週期不同
auto型別區域性變數就是普通的區域性變數(不加修飾的區域性變數預設為該型別)。該型別區域性變數儲存在棧上,在動態儲存區,生命週期僅限於定義它的函式,函式結束,它就自動釋放。static型別區域性變數儲存在靜態儲存區,在程式整個執行期間都不釋放。兩者之間的作用域相同,但生存期不同。
2. static區域性變數在所處模組在初次執行時進行初始化工作,且只操作一次。
3. 對於區域性靜態變數,如果不賦初值,編譯期會自動賦初值0或空字元,而auto型別的初值是不確定的。(對於c++中的class物件例外,class的物件例項如果不初始化,則會自動呼叫預設建構函式,不管是否是static型別)
特點: static區域性變數的」記憶性」與生存期的」全域性性」
二、外部靜態變數/函式
在c中 static有了第二種含義:用來表示不能被其它檔案訪問的全域性變數和函式。但為了限制全域性變數/函式的作用域, 函式或變數前加static使得函式成為靜態函式。但此處「static」的含義不是指儲存方式,而是指對函式的作用域僅侷限於本檔案(所以又稱內部函 數)。注意此時, 對於外部(全域性)變數, 不論是否有static限制, 它的儲存區域都是在靜態儲存區,生存期都是全域性的. 此時的static只是起作用域限制作用, 限定作用域在本模組(檔案)內部.
使用內部函式的好處是:不同的人編寫不同的函式時,不用擔心自己定義的函式,是否會與其它檔案中的函式同名。
三、靜態資料成員/成員函式(c++特有)
c+ +重用了這個關鍵字,並賦予它與前面不同的第三種含義:表示屬於乙個類而不是屬於此類的任何特定物件的變數和函式. 這是與普通成員函式的最大區別,
也是其應用所在, 比如在對某乙個類的物件進行計數時, 計數生成多少個類的例項,
就可以用到靜態資料成員. 在這裡面, static既不是限定作用域的, 也不是擴充套件生存期的作用, 而是指示變數/函式在此類中的唯一性. 這也是」屬於乙個類而不是屬於此類的任何特定物件的變數和函式」的含義. 因為它是對整個類來說是唯一的,因此不可能屬於某乙個例項物件的. (針對靜態資料成員而言, 成員函式不管是否是static, 在記憶體中只有乙個副本, 普通成員函式呼叫時, 需要傳入this指標, static成員函式呼叫時, 沒有this指標.
C 中的static關鍵字總結
c 的static有兩種用法 面向過程程式設計中的static和物件導向程式設計中的static。前者應用於普通變數和函式,不涉及類 後者主要說明static在類中的作用。1.面向過程設計中的static 1.1靜態全域性變數 在全域性變數前,加上關鍵字static,該變數就被定義成為乙個靜態全域性...
C 中的static關鍵字的總結
c 的static有兩種用法 面向過程程式設計中的static和物件導向程式設計中的static。前者應用於普通變數和函式,不涉及類 後者主要說明static在類中的作用。1.面向過程設計中的static 1.1靜態全域性變數 在全域性變數前,加上關鍵字static,該變數就被定義成為乙個靜態全域性...
C 中的static關鍵字的總結
c 的static有兩種用法 面向過程程式設計中的static和物件導向程式設計中的static。前者應用於普通變數和函式,不涉及類 後者主要說明static在類中的作用。1.面向過程設計中的static 1.1靜態全域性變數 在全域性變數前,加上關鍵字static,該變數就被定義成為乙個靜態全域性...