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。
- 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;//static成員變量不能在構造函數初始化列表中初始化,因爲它不屬於某個對象。
- cosnt int Test::c=0;//注意:給靜態成員變量賦值時,不需要加static修飾符。但要加cosnt
cosnt成員函數主要目的是防止成員函數修改對象的內容。即const成員函數不能修改成員變量的值,但可以訪問成員變量。當方法成員函數時,該函數只能是const成員函數。
static成員函數主要目的是作爲類作用域的全局函數。不能訪問類的非靜態數據成員。類的靜態成員函數沒有this指針,這導致:1、不能直接存取類的非靜態成員變量,調用非靜態成員函數2、不能被聲明爲virtual
關於static、const、static cosnt、const static成員的初始化問題:
1、類裏的const成員初始化:
在一個類裏建立一個const時,不能給他初值
- class foo
- {
- public:
- foo():i(100){}
- private:
- const int i=100;//error!!!
- };
- //或者通過這樣的方式來進行初始化
- foo::foo():i(100)
- {}
2、類裏的static成員初始化:
類中的static變量是屬於類的,不屬於某個對象,它在整個程序的運行過程中只有一個副本,因此不能在定義對象時 對變量進行初始化,就是不能用構造函數進行初始化,其正確的初始化方法是:
數據類型 類名::靜態數據成員名=值;
- class foo
- {
- public:
- foo();
- private:
- static int i;
- };
- int foo::i=20;
- 這表明:
- 1、初始化在類體外進行,而前面不加static,以免與一般靜態變量或對象相混淆
- 2、初始化時不加該成員的訪問權限控制符private、public等
- 3、初始化時使用作用域運算符來表明它所屬的類,因此,靜態數據成員是類的成員而不是對象的成員。
3、類裏的static cosnt 和 const static成員初始化
這兩種寫法的作用一樣,爲了便於記憶,在此值說明一種通用的初始化方法:
- class Test
- {
- public:
- static const int mask1;
- const static int mask2;
- };
- const Test::mask1=0xffff;
- const Test::mask2=0xffff;
- //它們的初始化沒有區別,雖然一個是靜態常量一個是常量靜態。靜態都將存儲在全局變量區域,其實最後結果都一樣。可能在不同編譯器內,不同處理,但最後結果都一樣。
這是一個完整的例子:
- #ifdef A_H_
- #define A_H_
- #include <iostream>
- using namespace std;
- class A
- {
- public:
- A(int a);
- static void print();//靜態成員函數
- private:
- static int aa;//靜態數據成員的聲明
- static const int count;//常量靜態數據成員(可以在構造函數中初始化)
- const int bb;//常量數據成員
- };
- int A::aa=0;//靜態成員的定義+初始化
- const int A::count=25;//靜態常量成員定義+初始化
- A::A(int a):bb(a)//常量成員的初始化
- {
- aa+=1;
- }
- void A::print()
- {
- cout<<"count="<<count<<endl;
- cout<<"aa="<<aa<<endl;
- }
- #endif
- void main()
- {
- A a(10);
- A::print();//通過類訪問靜態成員函數
- a.print();//通過對象訪問靜態成員函數
- }
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/