基本介紹
C#與C++的static有兩種用法:面向過程程序設計中的static和面向對象程序設計中的static。前者應用于普通變量和函數,不涉及類;後者主要說明static在類中的作用。
在全局變量前,加上關鍵字static,該變量就被定義成為一個靜态全局變量。
未經初始化的靜态全局變量會被程序自動初始化為0(在函數體内聲明的自動變量的值是随機的,除非它被顯式初始化,而在函數體外被聲明的自動變量也會被初始化為0);靜态全局變量在聲明它的整個文件都是可見的,而在文件之外是不可見的;靜态變量都在全局數據區分配内存,包括後面将要提到的靜态局部變量。
在局部變量前,加上關鍵字static,該變量就被定義成為一個靜态局部變量。
通常,在函數體内定義了一個變量,每當程序運行到該語句時都會給該局部變量分配棧内存。但随着程序退出函數體,系統就會收回棧内存,局部變量也相應失效。
但有時候我們需要在兩次調用之間對變量的值進行保存。通常的想法是定義一個全局變量來實現。但這樣一來,變量已經不再屬于函數本身了,不再僅受函數的控制,給程序的維護帶來不便。
靜态局部變量正好可以解決這個問題。靜态局部變量保存在全局數據區,而不是保存在棧中,每次的值保持到下一次調用,直到下次賦新值。
在函數的返回類型前加上static關鍵字,函數即被定義為靜态函數。靜态函數與普通函數不同,它隻能在聲明它的文件當中可見,不能被其它文件使用。
靜态數據成員存儲在全局數據區。靜态數據成員定義時要分配空間,所以不能在類聲明中定義。在Example 5中,語句int Myclass::Sum=0;是定義靜态數據成員;靜态數據成員和普通數據成員一樣遵從public,protected,private訪問規則;因為靜态數據成員在全局數據區分配内存,屬于本類的所有對象共享,所以,它不屬于特定的類對象,在沒有産生類對象時其作用域就可見,即在沒有産生類的實例時,我們就可以操作它;靜态數據成員初始化與一般數據成員初始化不同。
與靜态數據成員一樣,我們也可以創建一個靜态成員函數,它為類的全部服務而不是為某一個類的具體對象服務。靜态成員函數與靜态數據成員一樣,都是類的内部 實現,屬于類定義的一部分。普通的成員函數一般都隐含了一個this指針,this指針指向類的對象本身,因為普通成員函數總是具體的屬于某個類的具體對象的。
通常情況下,this 是缺省的。如函數fn()實際上是this->fn()。但是與普通函數相比,靜态成員函數由于不是與任何的對象相聯系,因此它不具有this指針。從這個意義上講,它無法訪問屬于類對象的非靜态數據成員,也無法訪問非靜态成員函數,它隻能調用其馀的靜态成員函數。
相關作用
函數内部定義的變量,在程序執行到它的定義處時,編譯器為它在棧上分配空間,大家知道,函數在棧上分配的空間在此函數執行結束時會釋放掉,這樣就産生了一個問題: 如果想将函數中此變量的值保存至下一次調用時,如何實現? 最容易想到的方法是定義一個全局的變量,但定義為一個全局變量有許多缺點,最明顯的缺點是破壞了此變量的訪問範圍(使得在此函數中定義的變量,不僅僅受此函數控制)。
内部機制
靜态數據成員要在程序一開始運行時就必須存在。因為函數在程序運行中被調用,所以靜态數據成員不能在任何函數内分配空間和初始化。
這樣,它的空間分配有三個可能的地方,一是作為類的外部接口的頭文件,那裡有類聲明;二是類定義的内部實現,那裡有類的成員函數定義;三是應用程序的main()函數前的全局數據聲明和定義處。
靜态數據成員要實際地分配空間,故不能在類的聲明中定義(隻能聲明數據成員)。類聲明隻聲明一個類的“尺寸和規格”,并不進行實際的内存分配,所以在類聲明中寫成定義是錯誤的。它也不能在頭文件中類聲明的外部定義,因為那會造成在多個使用該類的源文件中,對其重複定義。
static被引入以告知編譯器,将變量存儲在程序的靜态存儲區而非棧上空間,靜态數據成員按定義出現的先後順序依次初始化,注意靜态成員嵌套時,要保證所嵌套的成員已經初始化了。消除時的順序是初始化的反順序。
相關優勢
可以節省内存,因為它是所有對象所公有的,因此,對多個對象來說,靜态數據成員隻存儲一處,供所有對象共用。靜态數據成員的值對每個對象都是一樣,但它的值是可以更新的。隻要對靜态數據成員的值更新一次,保證所有對象存取更新後的相同的值,這樣可以提高時間效率。



















