C++ 類的靜態(tài)成員詳細(xì)講解

在C++中疤剑,靜態(tài)成員是屬于整個類的而不是某個對象璃谨,靜態(tài)成員變量只存儲一份供所有對象共用。所以在所有對象中都可以共享它豁辉。使用靜態(tài)成員變量實現(xiàn)多個對象之間的數(shù)據(jù)共享不會破壞隱藏的原則阳柔,保證了安全性還可以節(jié)省內(nèi)存焰枢。靜態(tài)成員的定義或聲明要加個關(guān)鍵static。靜態(tài)成員可以通過雙冒號來使用即<類名>::<靜態(tài)成員名>舌剂。

在C++中類的靜態(tài)成員變量和靜態(tài)成員函數(shù)是個容易出錯的地方济锄,本文先通過幾個例子來總結(jié)靜態(tài)成員變量和成員函數(shù)使用規(guī)則,再給出一個實例來加深印象霍转。希望閱讀本文可以使讀者對類的靜態(tài)成員變量和成員函數(shù)有更為深刻的認(rèn)識拟淮。

第一個例子,通過類名調(diào)用靜態(tài)成員函數(shù)和非靜態(tài)成員函數(shù)

class Point  
{  
public:   
    void init()  
    {    
    }  
    static void output()  
    {  
    }  
};  
void main()  
{  
    Point::init();  
    Point::output();  
}  

編譯出錯:error C2352: 'Point::init' : illegal call of non-static member function
結(jié)論1:不能通過類名來調(diào)用類的非靜態(tài)成員函數(shù)谴忧。

第二個例子很泊,通過類的對象調(diào)用靜態(tài)成員函數(shù)和非靜態(tài)成員函數(shù)
將上例的main()改為:

void main()  
{  
    Point pt;  
    pt.init();  
    pt.output();  
}  

編譯通過。
結(jié)論2:類的對象可以使用靜態(tài)成員函數(shù)和非靜態(tài)成員函數(shù)沾谓。

第三個例子委造,在類的靜態(tài)成員函數(shù)中使用類的非靜態(tài)成員

#include   
class Point  
{  
public:   
    void init()  
    {    
    }  
    static void output()  
    {  
        printf("%d\n", m_x);  
    }  
private:  
    int m_x;  
};  
void main()  
{  
    Point pt;  
    pt.output();  
}  

編譯出錯:error C2597: illegal reference to data member 'Point::m_x' in a static member function
因為靜態(tài)成員函數(shù)屬于整個類,在類實例化對象之前就已經(jīng)分配空間了均驶,而類的非靜態(tài)成員必須在類實例化對象后才有內(nèi)存空間昏兆,所以這個調(diào)用就出錯了,就好比沒有聲明一個變量卻提前使用它一樣妇穴。
結(jié)論3:靜態(tài)成員函數(shù)中不能引用非靜態(tài)成員爬虱。

第四個例子隶债,在類的非靜態(tài)成員函數(shù)中使用類的靜態(tài)成員

class Point  
{  
public:   
    void init()  
    {    
        output();  
    }  
    static void output()  
    {  
    }  
};  
void main()  
{  
    Point pt;  
    pt.output();  
}  

編譯通過。
結(jié)論4:類的非靜態(tài)成員函數(shù)可以調(diào)用用靜態(tài)成員函數(shù)跑筝,但反之不能死讹。

第五個例子,使用類的靜態(tài)成員變量

#include   
class Point  
{  
public:   
    Point()  
    {    
        m_nPointCount++;  
    }  
    ~Point()  
    {  
        m_nPointCount--;  
    }  
    static void output()  
    {  
        printf("%d\n", m_nPointCount);  
    }  
private:  
    static int m_nPointCount;  
};  
void main()  
{  
    Point pt;  
    pt.output();  
}  

按Ctrl+F7編譯無錯誤曲梗,按F7生成EXE程序時報鏈接錯誤
error LNK2001: unresolved external symbol "private: static int Point::m_nPointCount" (?m_nPointCount@Point@@0HA)
這是因為類的靜態(tài)成員變量在使用前必須先初始化赞警。
在main()函數(shù)前加上int Point::m_nPointCount = 0;
再編譯鏈接無錯誤,運行程序?qū)⑤敵?虏两。
結(jié)論5:類的靜態(tài)成員變量必須先初始化再使用愧旦。

結(jié)合上面的五個例子,對類的靜態(tài)成員變量和成員函數(shù)作個總結(jié):
一定罢。靜態(tài)成員函數(shù)中不能調(diào)用非靜態(tài)成員笤虫。
二。非靜態(tài)成員函數(shù)中可以調(diào)用靜態(tài)成員祖凫。因為靜態(tài)成員屬于類本身琼蚯,在類的對象產(chǎn)生之前就已經(jīng)存在了,所以在非靜態(tài)成員函數(shù)中是可以調(diào)用靜態(tài)成員的蝙场。
三凌停。靜態(tài)成員變量使用前必須先初始化(如int MyClass::m_nNumber = 0;)粱年,否則會在linker時出錯售滤。

再給一個利用類的靜態(tài)成員變量和函數(shù)的例子以加深理解,這個例子建立一個學(xué)生類台诗,每個學(xué)生類的對象將組成一個雙向鏈表完箩,用一個靜態(tài)成員變量記錄這個雙向鏈表的表頭,一個靜態(tài)成員函數(shù)輸出這個雙向鏈表拉队。

#include   
#include   
const int MAX_NAME_SIZE = 30;    
  
class Student    
{    
public:    
    Student(char *pszName);  
    ~Student();  
public:  
    static void PrintfAllStudents();  
private:    
    char    m_name[MAX_NAME_SIZE];    
    Student *next;  
    Student *prev;  
    static Student *m_head;  
};    
  
Student::Student(char *pszName)  
{    
    strcpy(this->m_name, pszName);  
  
    //建立雙向鏈表弊知,新數(shù)據(jù)從鏈表頭部插入。  
    this->next = m_head;  
    this->prev = NULL;  
    if (m_head != NULL)  
        m_head->prev = this;  
    m_head = this;    
}    
  
Student::~Student ()//析構(gòu)過程就是節(jié)點的脫離過程    
{    
    if (this == m_head) //該節(jié)點就是頭節(jié)點粱快。  
    {  
        m_head = this->next;  
    }  
    else  
    {  
        this->prev->next = this->next;  
        this->next->prev = this->prev;  
    }  
}    
  
void Student::PrintfAllStudents()  
{  
    for (Student *p = m_head; p != NULL; p = p->next)  
        printf("%s\n", p->m_name);  
}  
  
Student* Student::m_head = NULL;    
  
void main()    
{     
    Student studentA("AAA");  
    Student studentB("BBB");  
    Student studentC("CCC");  
    Student studentD("DDD");  
    Student student("MoreWindows");  
    Student::PrintfAllStudents();  
}  

程序?qū)⑤敵觯?/p>

Paste_Image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秩彤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子事哭,更是在濱河造成了極大的恐慌漫雷,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳍咱,死亡現(xiàn)場離奇詭異降盹,居然都是意外死亡,警方通過查閱死者的電腦和手機谤辜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門蓄坏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來价捧,“玉大人,你說我怎么就攤上這事涡戳〗狍” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵妹蔽,是天一觀的道長椎眯。 經(jīng)常有香客問我,道長胳岂,這世上最難降的妖魔是什么编整? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮乳丰,結(jié)果婚禮上掌测,老公的妹妹穿的比我還像新娘。我一直安慰自己产园,他們只是感情好汞斧,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著什燕,像睡著了一般粘勒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屎即,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天庙睡,我揣著相機與錄音,去河邊找鬼技俐。 笑死乘陪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雕擂。 我是一名探鬼主播啡邑,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼井赌!你這毒婦竟也來了谤逼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤仇穗,失蹤者是張志新(化名)和其女友劉穎流部,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仪缸,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡贵涵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宾茂。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓷马,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出跨晴,到底是詐尸還是另有隱情欧聘,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布端盆,位于F島的核電站怀骤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏焕妙。R本人自食惡果不足惜蒋伦,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望焚鹊。 院中可真熱鬧痕届,春花似錦、人聲如沸末患。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽璧针。三九已至嚷炉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間探橱,已是汗流浹背申屹。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留走搁,地道東北人独柑。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓迈窟,卻偏偏與公主長得像私植,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子车酣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容