C++靜態成員數據—定義、初始化
2020-05-23 14:25:51
供稿:網友
由于內存的空間有限,我們常常關心已經使用掉了多少內存空間。如果我們修改上一章的鏈表程序(程序15.5),要能計算出整個程序一共產生了多少鏈表結點,我們該怎么做呢?
顯然,我們需要一個計數器。每產生一個結點,計數器就加一;每消除一個結點,計數器就減一。由于結點的產生和消除只會與鏈表類或結點類的某些成員函數有關,所以這個計數器只能是一個全局變量了(全局變量的概念見11.1節),否則它將無法被各個成員函數訪問和修改。
不過使用全局變量會帶來嚴重的安全性問題。產生了多少個鏈表結點明明是和結點類有關的,卻沒有被封裝在結點類里面。任何函數都能修改這個全局變量,不得不讓我們擔憂。
封裝在類內部的數據是成員數據。想象一下,如果我們給鏈表結點類添加一個成員數據count,那么鏈表結點類的定義就是這樣:
class Node//定義一個鏈表結點類
{
public:
……
//成員函數同程序15.5
private:
int idata;//存儲數據保密
char cdata;//存儲數據保密
Node *prior;//前驅結點的存儲位置保密
Node *next;//后繼結點的存儲位置保密
int count;//新來的成員函數,用于記錄產生了多少個結點
};
現在計數器是一個成員數據,可以被鏈表結點類的成員函數訪問,也保證它不會被隨便修改。但如果我們創建了三個結點對象a、b、c之后,我們發現a.count、b.count和c.count是三個互不相關的變量,也就是說它們的值可能是不一致的。更麻煩的是,我們不知道還會產生多少結點對象,如果新增一個結點對象,那么之前的每一個結點對象的count都要發生變化!
所以,我們需要一種方法,既能把count封裝在類的內部,又能使各個對象的count相同。
靜態成員數據
我們將產生的結點個數記為count,它不是某一個結點所具有的屬性,而應該是整個鏈表結點類所具有的屬性,或者說它是各個結點對象的共有屬性。
如果我們把idata和cdata比作每個結點的私有財產,那么count就是所有結點的共有財產。count能被任何一個結點使用,但事實上無論有多少個結點,count只有一個。這樣就不會發生a.count、b.count和c.count各不相同的情況了。在C++中,用靜態成員數據(Static Data Member)來描述這種共有屬性。與一般的成員數據類似,靜態成員數據也可以分為公有(Public)的和私有(Private)的。靜態成員數據的聲明方法為:
static 數據類型成員變量名;
下面我們來看看如何給鏈表結點類增加一個靜態成員數據:
class Node//定義一個鏈表結點類
{
public:
……
//成員函數同程序15.5
private:
int idata;//存儲數據保密
char cdata;//存儲數據保密
Node *prior;//前驅結點的存儲位置保密
Node *next;//后繼結點的存儲位置保密
static int count;//私有靜態成員數據,用于記錄產生了多少個結點
};
靜態成員數據的初始化
由于靜態成員數據不是僅僅屬于某一個具體對象的,所以它不能在構造函數中被初始化。(否則豈不是每創建一個對象,靜態成員數據都要被初始化一次?)如果類的頭文件會被直接或間接地重復包含,則靜態成員數據也會被重復初始化。為了避免這個問題,我們可以將類的聲明和定義分離,如果忘記了這個問題可參見11.2節。如果類的頭文件絕對不會被重復包含,那么把靜態成員數據的初始化放在類的頭文件中也是可以勉強接受的。
靜態成員數據的初始化語句為:
數據類型類名::靜態成員數據=初始值;