【轉】C++中static用法總結
地址:https://www.cnblogs.com/qiaoconglovelife/p/5323086.html
1.用於區域性變數
C++中區域性變數有三種:
(1)auto:此關鍵詞常常省略。auto type a 常常簡寫為type a。
如:int a=auto int a
儲存在記憶體的棧中,只在此區域性區域有定義,程式執行過此區域性區域自動釋放。
(2)static:有以下特點:
- 宣告在區域性區域,第一次執行時定義,以後就不再定義;
- 同auto和register,只在其定義的區域性區域有定義;
- 區別與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(){};
};