天天看點

C++靜态成員函數小結

類中的靜态成員真是個讓人愛恨交加的特性。我決定好好總結一下靜态類成員的知識點,以便自己在以後面試中,在此類問題上不在被動。 

靜态類成員包括靜态資料成員和靜态函數成員兩部分。 

一 靜态資料成員: 

類體中的資料成員的聲明前加上static關鍵字,該資料成員就成為了該類的靜态資料成員。和其他資料成員一樣,靜态資料成員也遵守public/protected/private通路規則。同時,靜态資料成員還具有以下特點: 

1.靜态資料成員的定義。 

靜态資料成員實際上是類域中的全局變量。是以,靜态資料成員的定義(初始化)不應該被放在頭檔案中。 

其定義方式與全局變量相同。舉例如下: 

xxx.h檔案 
class base
           
{ 
private: 
<span style="white-space:pre">	</span>static const int _i;//聲明,标準c++支援有序類型在類體中初始化,但vc6不支援。 
}; 

xxx.cpp檔案 
const int base::_i=10;//定義(初始化)時不受private和protected通路限制. 
           

注:不要試圖在頭檔案中定義(初始化)靜态資料成員。在大多數的情況下,這樣做會引起重複定義這樣的錯誤。即使加上#ifndef #define #endif或者#pragma once也不行。 

2.靜态資料成員被 類 的所有對象所共享,包括該類派生類的對象。即派生類對象與基類對象共享基類的靜态資料成員。舉例如下: 

class base
           
{ 
public : 
<span style="white-space:pre">	</span>static int _num;//聲明 
}; 
int base::_num=0;//靜态資料成員的真正定義 

class derived:public base
           
{ 
}; 

main() 
{ 
<span style="white-space:pre">	</span>base a; 
<span style="white-space:pre">	</span>derived b; 
<span style="white-space:pre">	</span>a._num++; 
<span style="white-space:pre">	</span>cout<<"base class static data number _num is"<<a._num<<endl; 
<span style="white-space:pre">	</span>b._num++; 
<span style="white-space:pre">	</span>cout<<"derived class static data number _num is"<<b._num<<endl; 
} 
// 結果為1,2;可見派生類與基類共用一個靜态資料成員。 
           

3.靜态資料成員可以成為成員函數的可選參數,而普通資料成員則不可以。舉例如下:

class base
           
{ 
public : 
<span style="white-space:pre">	</span>static int _staticVar; 
<span style="white-space:pre">	</span>int _var; 
<span style="white-space:pre">	</span>void foo1(int i=_staticVar);//正确,_staticVar為靜态資料成員 
<span style="white-space:pre">	</span>void foo2(int i=_var);//錯誤,_var為普通資料成員 
}; 
           

4.★靜态資料成員的類型可以是所屬類的類型,而普通資料成員則不可以。普通資料成員的隻能聲明為 所屬類類型的 指針或引用。舉例如下: 

class base
           
{ 
public : 
<span style="white-space:pre">	</span>static base _object1;//正确,靜态資料成員 
<span style="white-space:pre">	</span>base _object2;//錯誤 
<span style="white-space:pre">	</span>base *pObject;//正确,指針 
<span style="white-space:pre">	</span>base &mObject;//正确,引用 
}; 
           

5.★這個特性,我不知道是屬于标準c++中的特性,還是vc6自己的特性。 

靜态資料成員的值在const成員函數中可以被合法的改變。舉例如下: 

class base
           
{ 
<span style="white-space:pre">	</span>public: 
<span style="white-space:pre">	</span>base(){_i=0;_val=0;<span style="font-family: Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;">}</span>
           
<span style="white-space:pre">	</span>mutable int _i; 
<span style="white-space:pre">	</span>static int _staticVal; 
<span style="white-space:pre">	</span>int _val; 
<span style="white-space:pre">	</span>void test() const<span style="white-space:pre">	<span style="font-family: Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px;">//const 成員函數</span></span>
           
<span style="white-space:pre">	</span>{<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>_i++;//正确,mutable資料成員 
<span style="white-space:pre">		</span>_staticVal++;//正确,static資料成員 
<span style="white-space:pre">		</span>_val++;//錯誤 
<span style="white-space:pre">	</span>} 
}; 
int base::_staticVal=0; 
           

二,靜态成員函數 

靜态成員函數沒有什麼太多好講的。 

1.靜态成員函數的位址可用普通函數指針儲存,而普通成員函數位址需要用 類成員函數指針來儲存。舉例如下: 

class base
           
{ 
<span style="white-space:pre">	</span>static int func1(); 
<span style="white-space:pre">	</span>int func2(); 
}; 

int (*pf1)()=&base::func1;//普通的函數指針 
int (base::*pf2)()=&base::func2;//成員函數指針 
           

2.靜态成員函數不可以調用類的非靜态成員。因為靜态成員函數不含this指針。 

3.靜态成員函數不可以同時聲明為 virtual、const、volatile函數。舉例如下: 

class base
           
{ 
<span style="white-space:pre">	</span>virtual static void func1();//錯誤 
<span style="white-space:pre">	</span>static void func2() const;//錯誤 
<span style="white-space:pre">	</span>static void func3() volatile;//錯誤 
}; 
           

最後要說的一點是,靜态成員是可以獨立通路的,也就是說,無須建立任何對象執行個體就可以通路。

繼續閱讀