1. 程式人生 > >C++類靜態成員變數與類靜態成員函式

C++類靜態成員變數與類靜態成員函式

    當將類的某個資料成員宣告為static時,該靜態資料成員只能被定義一次,而且要被同類的所有物件共享。各個物件都擁有類中每一個普通資料成員的副本,但靜態資料成員只有一個例項存在,與定義了多少類的物件無關。靜態方法就是與該類相關的,是類的一種行為,而不是與該類的例項物件相關。

    靜態成員變數不能在類中初始化,實際上類的定義只是在描述物件的藍圖,在其中指定初值是不允許的。也不能在類的建構函式中初始化靜態成員變數,因為靜態成員變數為類的各個物件共享,否則每次建立一個類的物件則靜態成員變數都要被重新初始化。

    從另外的角度考慮,靜態成員變數不可在類體內進行賦值,因為它是被所有該類的物件所共享的,如果你在一個物件裡給它賦值,其他物件裡的該成員變數也會發生變化,因此,為了避免混亂,所以不可在類體內對靜態成員變數進行賦值。

    靜態成員的值對所有的物件是一樣的。靜態成員可以被初始化,但只能在類體外進行初始化。一般形式:

    資料型別類名::靜態資料成員名=初值

    注意:不能用引數初始化表對靜態成員初始化。如果不對靜態成員變數進行顯示的初始化,一般系統預設初始為0。

    靜態成員是類所有的物件的共享的成員,而不是某個物件的成員。它在物件中不佔用儲存空間,這個屬性為整個類所共有,不屬於任何一個具體物件。所以靜態成員不能在類的內部初始化。靜態成員變數的用途之一是統計有多少個物件實際存在,比如宣告一個學生類,其中一個成員為學生總數,則這個變數就應當宣告為靜態變數,應該根據實際需求來設定成員變數。

例如:

#include "iostream"
using namespace std;

class test
{
private:
     int x;
     int y;
public:
     static int num;
     static int Getnum()
     {
          //x+=5;   // 這行程式碼是錯誤的,靜態成員函式不能呼叫非靜態資料成員.
          num+=15;
          return num;
     }
};

int test::num = 10;

int main(void)
{
     test a;
     cout<<test::num<<endl;        //10
     test::num = 20;
     cout<<test::num<<endl;        //20
     cout<<test::Getnum()<<endl;   //35
     cout<<a.Getnum()<<endl;       //50

     return 0;
}

    通過上例可知:x+=5; 這行程式碼是錯誤的。另外,靜態成員函式在類外實現以及靜態成員變數在類外初始化時無須加static關鍵字,否則是錯誤的。若在類的體外來實現上述的那個靜態成員函式,不能加static關鍵字,這樣寫就可以了:

 int test::Getnum()

 {

       .........

 }

1、static成員的所有者是類本身和物件,但是多個物件擁有一樣的靜態成員;

2、靜態成員變數不能在類定義裡邊初始化,只能在class body外初始化。

3、靜態成員仍然遵循public,private,protected訪問準則。

4、靜態成員函式沒有this指標,它不能返回非靜態成員,因為除了物件會呼叫它外,類本身也可以呼叫。

    靜態成員函式可以直接訪問該類的靜態成員變數和靜態成員函式,而不能直接訪問類的非靜態成員變數,如果一定要訪問非靜態成員變數則必須通過引數傳遞的方式得到一個物件名,然後通過物件名來訪問。

例如:

class Myclass
{
private:
        int a,b,c;
        static int Sum;    //宣告靜態資料成員
public:
        Myclass(int a,int b,int c);
        void GetSum();
};

int Myclass::Sum=0;       //定義並初始化靜態成員變數

Myclass::Myclass(int a,int b,int c)
{
        this->a=a;
        this->b=b;
        this->c=c;
        Sum+=a+b+c;
}
void Myclass::GetSum()
{
        cout <<"Sum=" <<Sum <<endl;
}
int main(void)
{
        Myclass me(10,20,30);
        me.GetSum();
        
        return 0;
}

由上例可知,非靜態成員函式Myclass(int a,int b,int c)和GetSum()都訪問了靜態資料成員Sum,非靜態成員函式可以任意地訪問靜態成員函式和靜態資料成員。但是,靜態成員函式不能訪問非靜態成員函式和非靜態資料成員。

關於靜態成員函式,可以總結為以下幾點:
1. 出現在類體外的函式定義不能指定關鍵字static;
2. 靜態成員之間可以相互訪問,包括靜態成員函式訪問靜態成員變數和訪問靜態成員函式;
3. 非靜態成員函式可以任意地訪問靜態成員函式和靜態成員變數;
4. 靜態成員函式不能訪問非靜態成員函式和非靜態成員變數;
5. 由於沒有this指標的額外開銷,因此靜態成員函式與類的全域性函式相比速度上會有少許的增長;
6. 呼叫靜態成員函式,可以用成員訪問操作符(.)和(->)為一個類的物件或指向類物件的指標呼叫靜態成員函式,或者"類名::靜態成員函式名"的方式呼叫;
7. 當同一類的所有物件使用一個量時,對於這個共用的量,可以用靜態資料成員變數,這個變數對於同一類的所有的物件都取相同的值。