類的靜態成員
面向對象的設計方法兼容數據的保護和共享,靜態成員的提出是為了解決不同對象之間數據共享問題的。例如要統計人員個數,出現次數等等都需要用到靜態處理。靜態成員,指的是在c++類中聲明成員時可以加上static關鍵字,這樣聲明的成員就叫做靜態成員(包括靜態數據成員和靜態成員函數)。
首先我們要搞懂靜態變量生存的周期
靜態成員變量在程序啟動時被分配,在程序結束時被釋放,其生命周期為程序的生命周期。基於這個類的所有對象只有一個靜態成員變量的拷貝,所以一個函數結束時,靜態變量仍然在內存中的靜態存儲區里保存,直到腳本結束才會被注銷。
1.靜態數據成員
如果我們需要面向對象中“類屬性”,這個屬性為整個類擁有,不屬於其中某一個對象,從而體現了整個類的數據共享。此時我們就用用static聲明靜態成員。
由於靜態數據成員不屬於任何一個對象,我么可以用類名對他進行訪問,一般用法是類名::標識符,但是在類中也要進行定義性聲明。類的靜態數據成員需要類之外定義是因為要單獨給他們分配空間。
例如書上5-4中具有靜態成員的point類
#include<iostream>
using namespace std;
class point {
public:
point(int x=0,int y=0):x(x),y(y){
count++;
}
point(point &p);
~point(){
count--;
}
void getX(){
cout << x;
}
void getY(){
cout << y;
}
void showcount(){
cout << "count=" << count << endl;
}
private:
int x,y;
static int count;//聲明
};
int point::count=0;//用類名限定靜態成員定義和初始化
point::point(point &p){
x=p.x;
y=p.y;
count++;
}
int main(){
point a(1,1);
a.showcount();
point b(a);
b.showcount();
return 0;
}

在這個簡單的例子中,我們可以看到point中的count被聲明為靜態,每新增一個對象count就加一。我們需要注意的就是count的定義和初始化在類外進行的。雖然這個count是私有成員在這種特殊場合可以進行初始化,但在其他函數例如主函數就不能調用count了。
2.靜態函數成員
上面例子中如果我們如何輸出count的初始化值呢,這時還沒有創建對象,如果我們直接這樣不出意外會報錯,因為這時我們不能直接通過類名調用函數。
main(){
point::showcount();
point a(1,1);
}

這時我們需要的就是靜態成員函數了。靜態成員函數就是通過使用static關鍵字聲明的函數。同靜態數據成員一樣,靜態成員函數也是屬於一個類,由同一個類所有對象共同擁有,也體現了數據共享。靜態成員函數可以直接訪問類的靜態數據和函數成員,而一般函數必須同過對象名。
這兩段代碼的區別只是將輸出函數改成了靜態類型,達到的輸出效果完全一樣。相比之下,靜態成員函數可以脫離對象直接調用,這是他很好的一個優點。
#include<iostream>
using namespace std;
class point {
public:
point(int x=0,int y=0):x(x),y(y){
count++;
}
point(point &p);
~point(){
count--;
}
void getX(){
cout << x;
}
void getY(){
cout << y;
}
static void showcount(){
cout << "count=" << count << endl;
}
private:
int x,y;
static int count;//聲明
};
int point::count=0;//用類名限定靜態成員定義和初始化
point::point(point &p){
x=p.x;
y=p.y;
count++;
}
int main(){
point::showcount();
point a(1,1);
point::showcount();
point b(a);
point::showcount();
return 0;
}

最后我們對比一下靜態成員函數和普通函數:
首先普通數據成員屬於類的一個具體的對象,只有對象被創建了,普通數據成員才會被分配內存。而靜態數據成員屬於整個類,即使沒有任何對象創建,類的靜態數據成員變量也存在。其次因為類的靜態數據成員的存在不依賴與於任何類對象的存在,類的靜態數據成員應該在代碼中被顯式地初始化,一般要在類外進行,例如上例。我們可以為靜態成員提供const整數類型的類內初始值,類的靜態成員函數無法直接訪問普通數據成員(可以通過對象名間接的訪問),而類的任何成員函數都可以訪問類的靜態數據成員。
