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卻不支持