static修飾局部變量
- 靜態局部變量存儲在全局靜態區
- 生存期為整個程序生命周期,但是其作用域仍與自動變量相同,只能在定義該變量的函數內使用該變量。退出該函數后,盡管該變量還繼續存在,但不能使用它。
- 靜態局部變量若在聲明時未賦以初值,則系統自動賦予0值。而對自動變量不賦初值,則其值是不定的。
static修飾全局變量
- 非靜態全局變量的作用域是整個源程序,也即在各個源文件中都是有效的。
- 而靜態全局變量則只在定義該變量的源文件內有效,在同一源程序的其它源文件中不能使用它?
?
二、C++ 中的static關鍵字(類中的static關鍵字)
1、static 數據成員
在類內數據成員的聲明前加上關鍵字static,該數據成員就是類內的靜態數據成員。
#include <iostream>
using namespace std;class Myclass {
public:Myclass(int a, int b, int c);void GetSum();private:int a, b, c;static int Sum; //聲明靜態數據成員
};int Myclass::Sum = 0; //定義并初始化靜態數據成員
//static int Myclass::Sum = 0; //注意加static, 是錯誤的 Myclass::Myclass(int a, int b, int c)
{this->a = a;this->b = b;this->c = c;Sum += a + b + c;
}void Myclass::GetSum()
{cout << "Sum = " << Sum << endl;
}int main()
{Myclass M(1, 2, 3);M.GetSum(); // cout 6 Myclass N(4, 5, 6);N.GetSum(); // cout 21 M.GetSum(); // cout 21
}
輸出結果:
?可以看出,static數據成員有以下特點:
(1). 對于非static數據成員,每個類對象都有自己的拷貝。而static數據成員被當作是類的成員。無論這個類的對象被定義了多少個,靜態數據成員在程序中也只有一份拷貝,由該類型的所有對象共享訪問
(2). 靜態數據成員存儲在全局數據區。靜態數據成員定義時才分配空間,所以不能在類聲明中定義。
在上例中,語句 int Myclass::Sum = 0; 是定義靜態數據成員;
(3). 靜態數據成員和普通數據成員一樣遵從public, protected, private 訪問規則;除了定義,定義不要管訪問規則。
(4). 因為靜態數據成員在全局數據區分配內存,屬于本類的所有對象共享,所以,它不屬于特定的類對象,在沒有產生類對象時其作用域就可見,即在沒有產生類的實例時,我們就可以操作它
(5). 靜態數據成員初始化與一般數據成員初始化不同。靜態數據成員初始化的格式為:
//<數據類型><類名>::<靜態數據成員名>=<值>
int Myclass::Sum=0;
(6). 類的靜態數據成員有兩種訪問形式:
//<類對象名>.<靜態數據成員名>
M.Sum = 0 //<類類型名>::<靜態數據成員名>
Myclass::Sum = 0
(7). 靜態數據成員主要用在各個對象都有相同的某項屬性的時候。比如對于一個存款類,每個實例的利息都是相同的。所以,應該把利息設為存款類的靜態數據成員。這有兩個好處,第一,不管定義多少個存款類對象,利息數據成員都共享分配在全局數據區的內存,所以節省存儲空間。第二,一旦利息需要改變時,只要改變一次,則所有存款類對象的利息全改變過來了;
?
2、static 成員函數
? static 成員函數,它為類的全部對象服務而不是為某一個類的具體對象服務。普通的成員函數一般都隱含了一個this指針,但靜態成員函數由于不是與任何的對象相聯系,因此它不具有this指針。從這個意義上講,它無法訪問屬于類對象的no-static數據成員,也無法訪問no-static成員函數,它只能調用其余的靜態成員函數。
#include <iostream>
using namespace std;class Myclass {
public:Myclass(int a, int b, int c);static void GetSum(); // 聲明靜態成員函數
private:int a, b, c;static int Sum; //聲明靜態數據成員
};int Myclass::Sum = 0;//定義并初始化靜態數據成員 Myclass::Myclass(int a, int b, int c)
{this->a = a;this->b = b;this->c = c;Sum += a + b + c; //非靜態成員函數可以訪問靜態數據成員
}//static void Myclass::GetSum(){...} //加上static是錯誤的
void Myclass::GetSum() //靜態成員函數的實現
{//cout<<a<<endl; //錯誤代碼,a是非靜態數據成員 cout << "Sum = " << Sum << endl; //靜態函數是能訪問靜態數據成員
}int main()
{Myclass M(1, 2, 3);M.GetSum();Myclass N(4, 5, 6);N.GetSum();Myclass::GetSum();
}
關于靜態成員函數,可以總結為以下幾點:
- (1). 在類體外,靜態函數的定義前不能加關鍵字static;
- (2).?static成員之間可以相互訪問,包括static成員函數訪問static數據成員和訪問static成員函數;
- (3). 非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員;
- (4). 靜態成員函數不能訪問非靜態成員函數和非靜態數據成員,只能訪問靜態的;
- (5). 由于沒有this指針的額外開銷,因此靜態成員函數與類的全局函數相比速度上會有少許的增長
- (6). 調用靜態成員函數,可以用成員訪問操作符(.)和(->)或直接用類名調用靜態成員函數
1
2
M.GetSum();??
Myclass::GetSum();?
// 調用類的靜態成員函數。
?