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