C++ static、const和static const 以及它們的初始化

http://blog.csdn.net/yjkwf/article/details/6067267?reload


      const定義的常量在超出其作用域之後其空間會被釋放,而static定義的靜態常量在函數執行後不會釋放其存儲空間。

      static表示的是靜態的。類的靜態成員函數、靜態成員變量是和類相關的,而不是和類的具體對象相關的。即使沒有具體對象,也能調用類的靜態成員函數和成員變量。一般類的靜態函數幾乎就是一個全局函數,只不過它的作用域限於包含它的文件中。

      在C++中,static靜態成員變量不能在類的內部初始化。在類的內部只是聲明,定義必須在類定義體的外部,通常在類的實現文件中初始化,如:double Account::Rate=2.25;static關鍵字只能用於類定義體內部的聲明中,定義時不能標示爲static

      在C++中,const成員變量也不能在類定義處初始化,只能通過構造函數初始化列表進行,並且必須有構造函數。

      const數據成員 只在某個對象生存期內是常量,而對於整個類而言卻是可變的因爲類可以創建多個對象,不同的對象其const數據成員的值可以不同。所以不能在類的聲明中初始化const數據成員,因爲類的對象沒被創建時,編譯器不知道const數據成員的值是什麼。

      const數據成員的初始化只能在類的構造函數的初始化列表中進行。要想建立在整個類中都恆定的常量,應該用類中的枚舉常量來實現,或者static cosnt。

  1. class Test  
  2. {  
  3. public:  
  4.       Test():a(0){}  
  5.       enum {size1=100,size2=200};  
  6. private:  
  7.       const int a;//只能在構造函數初始化列表中初始化  
  8.        static int b;//在類的實現文件中定義並初始化  
  9.       const static int c;//與 static const int c;相同。  
  10. };  
  11.   
  12. int Test::b=0;//static成員變量不能在構造函數初始化列表中初始化,因爲它不屬於某個對象。  
  13. cosnt int Test::c=0;//注意:給靜態成員變量賦值時,不需要加static修飾符。但要加cosnt  

      cosnt成員函數主要目的是防止成員函數修改對象的內容。即const成員函數不能修改成員變量的值,但可以訪問成員變量。當方法成員函數時,該函數只能是const成員函數。

      static成員函數主要目的是作爲類作用域的全局函數。不能訪問類的非靜態數據成員。類的靜態成員函數沒有this指針,這導致:1、不能直接存取類的非靜態成員變量,調用非靜態成員函數2、不能被聲明爲virtual

關於static、const、static cosnt、const static成員的初始化問題:

1、類裏的const成員初始化:

在一個類裏建立一個const時,不能給他初值

  1. class foo  
  2. {  
  3. public:  
  4.       foo():i(100){}  
  5. private:  
  6.       const int i=100;//error!!!  
  7. };  
  8. //或者通過這樣的方式來進行初始化  
  9. foo::foo():i(100)  
  10. {}  

2、類裏的static成員初始化:

      類中的static變量是屬於類的,不屬於某個對象,它在整個程序的運行過程中只有一個副本,因此不能在定義對象時 對變量進行初始化,就是不能用構造函數進行初始化,其正確的初始化方法是:

數據類型 類名::靜態數據成員名=值;

[c-sharp] view plaincopy
  1. class foo  
  2. {  
  3. public:  
  4.       foo();  
  5. private:  
  6.       static int i;  
  7. };  
  8.   
  9. int foo::i=20;  
  10. 這表明:  
  11. 1、初始化在類體外進行,而前面不加static,以免與一般靜態變量或對象相混淆  
  12. 2、初始化時不加該成員的訪問權限控制符privatepublic等  
  13. 3、初始化時使用作用域運算符來表明它所屬的類,因此,靜態數據成員是類的成員而不是對象的成員。  

3、類裏的static cosnt 和 const static成員初始化

      這兩種寫法的作用一樣,爲了便於記憶,在此值說明一種通用的初始化方法:

  1. class Test  
  2. {  
  3. public:  
  4.       static const int mask1;  
  5.       const static int mask2;  
  6. };  
  7. const Test::mask1=0xffff;  
  8. const Test::mask2=0xffff;  
  9. //它們的初始化沒有區別,雖然一個是靜態常量一個是常量靜態。靜態都將存儲在全局變量區域,其實最後結果都一樣。可能在不同編譯器內,不同處理,但最後結果都一樣。  

這是一個完整的例子:

  1. #ifdef A_H_  
  2. #define A_H_  
  3. #include <iostream>  
  4. using namespace std;  
  5. class A  
  6. {  
  7. public:  
  8.       A(int a);  
  9.       static void print();//靜態成員函數  
  10. private:  
  11.       static int aa;//靜態數據成員的聲明  
  12.        static const int count;//常量靜態數據成員(可以在構造函數中初始化)  
  13.        const int bb;//常量數據成員  
  14. };  
  15. int A::aa=0;//靜態成員的定義+初始化  
  16. const int A::count=25;//靜態常量成員定義+初始化  
  17. A::A(int a):bb(a)//常量成員的初始化  
  18. {  
  19.       aa+=1;  
  20. }  
  21. void A::print()  
  22. {  
  23.       cout<<"count="<<count<<endl;  
  24.       cout<<"aa="<<aa<<endl;  
  25. }  
  26. #endif  
  27. void main()  
  28. {  
  29.       A a(10);  
  30.       A::print();//通過類訪問靜態成員函數  
  31.       a.print();//通過對象訪問靜態成員函數  
  32. }  

 

          2、靜態數據成員最好不要在.h文件中進行定義(初始化),而是放在.cpp文件中定義(初始化)

3、靜態數據成員被類的所有對象所共享,包括類的派生類的所有對象;——即派生類和基類共享一個靜態成員

 4、靜態數據成員的類型可是所屬類自己,即在一個類中可以聲明該類自己的類型的靜態成員對象,但是,不可以定義普通的成員對象,(指針可以)

         5、在const成員函數中,可以修改static成員變量的值。普通成員變量的值,是不能修改的

          6、static成員函數只能訪問static成員,不能訪問非static成員,並且static成員函數不能定義爲virtual、const、volatile 函數

 

 

      和其他數據成員一樣,靜態數據成員也遵守public/protected/private訪問規則注意::僅僅是初始化時不遵守public/protected/private的規則。

        即:如果是private和protected的靜態成員,只能通過public的靜態成員函數進行調用,而不能通過類名直接訪問了。

1、靜態數據成員的定義(初始化)不能在頭文件中。 
     靜態數據成員實際上是類域中的全局變量。所以,
靜態數據成員的定義(初始化)不應該被放在頭文件中。 
    其定義方式與全局變量相同。舉例如下: 
xxx.h文件 
class base

{ 
       private: 
               static const int _i;           //聲明,標準c++支持有序類型在類體中初始化,但vc6不支持。 
}; 

xxx.cpp文件 
const int base::_i=10;                 
//僅僅在定義(初始化)時不受private和protected訪問限制. 

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

 

2、靜態數據成員     的所有對象所共享,包括該類派生類的對象。即派生類對象與基類對象共享基類的靜態數據成員。舉例如下: 
class base

{ 
       public : 
               static int _num;         //聲明 
}; 
int base::_num=0;                   //靜態數據成員的真正定義 

class derived:public base

{ 
}; 

main() 
{ 
      base a; 
      derived b; 
      a._num++; 
      cout<<"base class static data number _num is"<<a._num<<endl; 
      b._num++; 
      cout<<"derived class static data number _num is"<<b._num<<endl; 
} 
// 結果爲1,2;可見派生類與基類共用一個靜態數據成員。

 

3、靜態數據成員的類型可以是所屬類的類型而普通數據成員則不可以。普通數據成員的只能聲明爲所屬類類型的 指針或引用。舉例如下: 

class base{ 
        public : 
               static base _object1;                       //正確,靜態數據成員 
               base _object2;                                  //錯誤 
               base *pObject;                                  //正確,指針 
               base &mObject;                               //正確,引用 (引用需要在構造函數的參數初始化列表中初始化,如下:
};

這個類要能創建對象,需要定義帶有參數初始化列表的構造函數,如下:

class base{ 
       public : 
             static base _object1; //正確,靜態數據成員 
             base *pObject;            //正確,指針 
             base &mObject;         //正確,引用

             base():mObject(*this){}                
};

4、靜態數據成員的值在const成員函數中可以被合法的改變,而不破那個數據成員的值,不能在const成員函數中改變。

#include <iostream>
using namespace std;

class Student
{
 private:
  static int a;
  int b;
 public:
  void change() const;
  void setB(int b);
  int getB();
  static int getA();
};

void Student::change() const
{
          a++;         
 //這個可以,因爲a是static成員變量。
          b++;          
//不可以,因爲b是普通成員變量(如果b不是成員變量(是全局變量,普通參數,函數內部定義的臨時變量)也可以別修改),且是const函數
}
int Student::getA()
{
         return a;
}
void Student::setB(int b)
{
         this->b = b;
}
int Student::getB()
{
         return b;
}
int Student::a = 5;

int main(int argc,char *argv[])
{
       Student stu;
       stu.setB(10);
       stu.change();
       cout<<Student::getA()<<endl; 
       cout<<stu.getB()<<endl;
       return 0;
}

即:成員函數的const約束,只起作用於類的普通成員變量,對於全局變量,成員函數參數,成員函數內部的臨時變量起不到作用。

http://blog.163.com/xychenbaihu@yeah/blog/static/13222965520112894854489/

 

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章