淺出理解靜態成員函數(static member function)

來源:互聯網
上載者:User

  在轉入正題之前,我覺得應該先提出兩個我本人自訂的術語:類級成員(class level member)和對象級成員(object level member)。我不知道在C++領域裡是否已經有這樣的術語,只是我覺得這兩個術語可以很好地協助我們理解static member function。在這裡可以就有人想指正我了:本來成員(member)就是類專屬的一部分,還分什麼類級和對象級的。但我相信如果你看完本文後,你原來對static member function的那種一知半解,會演變成現在的“原來是這麼一回事”的話,你會覺得這是非常棒的兩個東西。所謂的類級成員就是指該成員是屬於類擁有的,一個類只有一個的;而所謂的對象級成員就是指該成員是屬於對象自己的,只要產生多少個該類的對象就會產生出多少個這樣的成員。如果你還是沒有理解其中的意思的話,不要緊,往下看吧,慢慢你就會明白了(其實也沒什麼,也只是static member與non static member的區別而已,只是我覺得這樣更利於理解而已)。

  non static member是屬於對象級成員函數,也就是說,每個屬於該類的對象都會產生一份屬於自己的成員。而static member是屬於類級成員,也就是說,無論該類產生多少個對象,而這種成員只會產生一個。為什麼static member function只能訪問static member data呢?就是因為static member data是屬於類級成員資料,non static member data是屬於對象級成員資料,而static member function是屬於類級成員函數,non static member function是屬於對象級成員函數。對於一個類級成員函數只能訪問到類級成員資料。因為類級成員是共用的,而對象級成員是私人的,私人的資料只能是由私人函數來讀取(可不要把這裡的共用與私人的關係和灰的聲明中的public與private的關係混淆了啊,這裡的私人是指對象私人,而後者是指類私人)。

  如果對於上面的解釋還是不太好理解為什麼類級成員只能訪問類級成員資料的話,那我就用實際來告訴你為什麼私人的對象資料不能由共用的函數來存取了。如有以下類的聲明:
class Point
{
public :
    void OutPut ();
    static void Init ( int, int );

private :
    int m_x;
    static int m_y;
};
int Point::m_y = 10;  //初始化static member data
Point ptA, ptB;

如果有以下函數的定義:
void
Point::OutPut ()    //正確
{
    cout <<"x=" <<x <<endl
         <<"y=" <<y <<endl;
}
void
Point::Init ( int x, int y )
{
    m_x = x;    //錯誤,m_x是對象級成員資料,Init()是類級成員函數
    m_y = y;    //正確,m_y和Init()都是類級成員
}

因為ptA和ptB都會產生屬於對象自己的m_x(如果定義更多Point的對象,將會產生更多)。對於OutPut()是毫無疑問沒問題的,因為ptA和ptB也會產生屬於自己OutPut(),對象自己的函數訪問屬於對象自己資料,這是理所當然的。但Init()只會產生一個,而ptA和ptB都有屬於自己m_x(各自互不侵犯),Init()怎麼知道應該訪問那個m_x呢(準確點應該說編譯器怎麼知道應該訪問那個的m_x),還是對於所有Point的對象的m_x都進行存取呢(那不就是侵犯私隱了嗎)。

  static member function還有另外一個在一般的語言教材上很少會提到的特點,我們在用MFC的時候會經常以“類名::類成員函數”這種方法來調用一個函數(當然我不是說只有MFC都有這樣的調用)。要使用這樣的調用方法是需要有一個條件的,就是這個類成員函數一定要是一個static member function。如果你不明白前面的解釋的話,你是不會想到這點的。那為什麼一定要是static member function才能這樣被調用呢,其實原理跟前面是一樣的,就是因為static member function只會產生一個。如果你還是想不到為什麼的話,那我就用實際來說明一切吧!沿用前面類的聲明,如果有以下的用法:

Point::Init ( 5, 5 );   //正確(這裡只討論它的調用方法,不討論它的定義是否正確),因為Init()是類級成員函數
ptA.Init ( 3, 3 );      //正確,既然Init()是共用的,ptA自然也可以用
Point::OutPut ();       //錯誤,OutPut()是對象級成員函數
ptA.OutPut ();          //正確,對象級的函數調用

正如前面所述的,ptA和ptB都會產生屬於自己OutPut(),編譯器怎麼知道應該調用那個對象的OutPut()呢,對象級的函數自然只能使用對象級的調用方法了。對於Init()卻是很好理解的,因為Init()由始至終只有一個,無論類級的調用,還是對象級的調用,都是合情合理的。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.