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

 

const定義的常量在函數執行之後其空間會被釋放,而static定義的靜態常量在函數執行後不會被釋放其空間。
static 表示的是靜態的。類的靜態成員函數,成員變量是和類相關的,不是和類的具體對象相關,即使沒有具體的對象,也能調用類的靜態成員函數,成員變量。一般的靜態函數幾乎就是一個全局函數,只不過它的作用域限於包含它的文件中。
 
在c++中,static靜態成員變量不能在類內部初始化。

        1)在C++編程裏面,有句話說,聚合變量不能放在頭文件裏面,當多個編譯單元引用時,編譯時候會報重複定義~!

        2)因爲你可能會加載多次頭文件 如果在頭文件中初始化的話 也就對static進行了多次初始化 這樣就會報錯 因此一般將static放在main中初始化
在c++中,const常量成員變量也不能在類定義處初始化,只能通過構造函數初始化列表進行,並且必須有構造函數。
 
const數據成員只在某個對象生存期內是常量,而對於整個類而言卻是可變的。因爲類可以創建多個對象,不同的對象其const數據成員的值可以不同。所以不能在類聲明中初始化const數據成員,因爲類的對象未被創建時,編譯器不知道const 數據成員的值是什麼。
const數據成員的初始化只能在類的構造函數的初始化表中進行。要想建立在整個類中都恆定的常量,應該用類中的枚舉常量來實現,或者static const。
如:
class Test
{
public:
    Test(): a(0){} 
       enum {size1=100, size2 = 200 };
private:
    const int a;  // 只能在構造函數初始化列表中初始化,這個似乎很少用到???
    static int b;
    const static int c; // 與static const int c;相同,可以在這裏定義(如果以後在類中需要使用該變量的話).
}
int Test::b = 0;  // 不能以成員列表初始化,不能在定義處促使化,因爲不屬於某個對象。
const int Test:: c = 0;//注意:給靜態成員變量賦值時,不在需要加static修飾。但const要加。
 
const 成員函數,主要的目的是防止修改對象的內容。即:int Fun() const; 不可以修改對象的數據,可以訪問對象的數據,訪問成員函數時,只能是const的,不能是non_const的成員函數。
static成員函數,主要的目的是作爲類作用域的全局函數。不能訪問類的非靜態數據成員。類的靜態成員函數的沒有this指針,這導致:
1.  不能直接存取類的非靜態成員變量,調用非靜態成員函數
2.  不能被聲明爲virtual
 
 
下面是關於static,const,static const , const static成員的初始化問題。
 
1.類裏的const成員初始化:
    在一個類裏建立一個const時,不能給它初值。像
class foo
{
private:
    const int i = 100;                // error !!!
public:
    foo(){}
    ......
};
這樣的初始化方式是不能通過編譯的,因爲在類對象裏進行了存儲空間分配,編譯器不能知道const的內容是什麼,所以不能把它用作編譯期間的常量。這意味着對於類裏的常數表達式來說,const就像它在C中一樣沒有作用。因此這個初始化工作必須發生在構造函數裏,並且,要在構造函數的某個特別的地方。因爲const必須在建立它的地方被初始化,所以在構造函數的主體裏,const必須已初始化了,否則,就只有等待,直到在構造函數主體以後的某個地方給它初始化,這意味着過一會兒纔給const初始化。當然,無法防止在在構造函數主體的不同地方改變const的值。
構造函數初始化表達式
class foo
{
 private:
    const int i = 100;
 public:
    foo(){......}
    ......
};
如果構造函數是在類外定義,則可以這樣寫:
class foo
{
 private:
    const int i;
 public:
    foo();
    ......
};
 foo ::foo() : i (100) {......}        // 初始化列表
 
2.類裏的static成員初始化:
    類中的static變量是屬於類的,不屬於某個對象,它在整個程序的運行過程中只有一個副本,因此不能在定義對象時對變量初始化,就是不能用構造函數來初始化。其正確的初始化方式是:
<數據類型><類名> ::<靜態數據成員名> = <值> ,例如
class foo
{
 private:
    static int i;
 public:
    foo();
    ......
};
int foo ::i = 100; 
 
這表明:     
(1)初始化在類體外進行,而前面不加static,以免與一般靜態變量或對象相混淆。 
(2)初始化時不加該成員的訪問權限控制符private,public等。 
(3)初始化時使用作用域運算符來標明它所屬類,因此,靜態數據成員是類的成員,而不是對象的成員。
 
3.類裏的static const 和const static成員初始化:
在找static成員的初始化學習資料時,我發現了網上有很多關於 static const 成員,也就是全局的靜態常量的初始化的資料。const成員要在構造函數初始化,而static成員在需要在在類體外初始化,那麼static const 和 const static 的成員應該在哪裏進行初始化呢?這兩個寫法又會有什麼不一樣嗎?其實他倆都一樣。在借閱《Thinking in c++》中文版188頁和做了相關實驗後,我認爲若在類內使用的話,static const 則必須在static const 定義之處進行初始化。其他情況在類裏外都行。
比如:
class Test{
           public:
                 static const int MASK1;
                 const static int MASK2;
           };
const int Test ::MASK1 = 0xFFFF;
const int Test ::MASK2 = 0xFFFF;
它們沒有區別,雖然 
一個是靜態常量, 
一個是常量靜態, 
靜態都將存儲在全局變量區域,其實最後結果都是一樣的。 
可能在不同編譯器內,不同處理,但是最後結果是一樣的。
 
下面是一個完整的例子:
#ifndef A_H_
#define A_H_
#include<iostream>
using namespace std;
 
   class A{
private:
    static int aa; //靜態數據成員聲明
    static const int count; //靜態常數據成員聲明(可以在此初始化)
    const int bb; //常數據成員
public:
    A(int a);
    static void print(); //靜態成員函數
};
 
   A::A(int a):bb(a) { //常成員的初始化
   aa += 1;
}
 
   void A::print() {
   cout << "connt=" << count<< endl;
   cout << "aa=" << aa << endl;
};
 
   int A::aa = 0; //靜態成員定義
const int A::count = 25; //靜態常成員初始化
#endif
 
   int main(){
 A a(10);
 A::print(); //通過類訪問靜態成員函數
 a.print(); //通過對象訪問靜態成員
}
 
但是注意:將static const datamember的申明放在頭文件中時,新的C++標準支持,但VC6.0卻不支持

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