關鍵字static有一段不尋常的歷史。
(一)起初,C引入關鍵字static是為了表示退出一個塊兒後依然存在的局部變量。在這種情況下術語“static”是有意義的:變量一致存在,當再次進入該塊時仍然存在。如:
[cpp]
int add()
{
static a=1;
return a++;
}
void main()
{
int b=0;
int i;
for(i=0;i<3;i++)
b+=add();
printf("b=%d\n",b);
}
result: b=3
int add()
{
static a=1;
return a++;
}
void main()
{
int b=0;
int i;
for(i=0;i<3;i++)
b+=add();
printf("b=%d\n",b);
}
result: b=3
(二)隨後,static在C中有了第二種含義,表示不能被其他文件訪問的全局變量和函數。為了避免引入一個新的關鍵字,關鍵字static被重用了。
(三)最後,C++第三次重用了這個關鍵字,與前面賦予的含義完全不一樣,這裡將其解釋為:屬於類且不屬於類對象的變量和函數。這個含義與Java相同。對於static,此時要從靜態域和靜態方法兩個方面考慮。
1、靜態域
如果將域定義為static,每個類中只有一個這樣的域。而每一個對象對於所有的實例域卻都有自己的一份拷貝。例如,假定需要給每一個雇員賦予唯一的標識碼。這裡給Employee類添加一個實例id和一個靜態域nextId:
[cpp]
class Employee
{
private int id;
private static int nextId=1;
}
class Employee
{
private int id;
private static int nextId=1;
}
現在,每一個雇員對象都有一個自己的id域,但這個類的所有實例將共享一個nextId域。換句話說,如果有1000個Employee類的對象,則有1000個實例域id。但是,只有一個靜態域nextId。即使沒有一個雇員對象,靜態域nextId也存在。它屬於類,而不屬於任何獨立的對象。
下面實現一個簡單的方法:
[cpp]
public void setid()
{
id=nextId;
nextId++;
}
public void setid()
{
id=nextId;
nextId++;
}
假定為harry設定雇員標識碼:
[cpp]
harry.setId();
harry.setId();
harry的id域被設置為靜態域nextId當前的值,並靜態域nextId的值加1:
[cpp]
harry.id=Employee.nextId;
Employee.nextId++;
harry.id=Employee.nextId;
Employee.nextId++;
2、靜態方法
靜態方法是一種不能向對象實施操作的方法。靜態方法不能操作對象,所以不能在靜態方法中訪問實例域。但是,靜態方法可以訪問自身類中的靜態域。所以,靜態方法一般用於以下兩種情況:
一個方法不需要訪問對象狀態,其所需參數都是通過顯示參數提供(例如:Math.pow)
一個方法只需訪問類的靜態域
靜態方法還有一種常見的用途。NumberFormat類使用factory方法產生不同風格的格式對象(這個我自己也沒看懂是什麼意思-P112)。
需要注意,不需要使用對象調用靜態方法。例如,不需要構造Math類對象就可以調用Math.pow。
同理,main方法就是一個靜態方法。main方法不對任何對象進行操作。事實上,在啟動程序時還沒有任何一個對象。靜態的main方法將執行並創建程序所需的對象。