1. C++變量的初始化方式
首先把需要初始化的成員變量分為幾類:
Ø 一般變量(int)
Ø 靜态成員變量(static int)
Ø 常量(const int )
Ø 靜态常量(static const int)
對應的初始化方式是:
Ÿ 一般變量可以在初始化清單裡或者構造函數裡初始化,不能直接初始化或者類外初始化
Ÿ 靜态成員變量必須在類外初始化
Ÿ 常量必須在初始化清單裡初始化
Ÿ 靜态常量必須隻能在定義的時候初始化(定義時直接初始化)
舉一個簡單的例子:
[cpp] view plain copy
- #include <iostream>
- #include <string>
- using namespace std;
- class Test
- {
- private:
- int a;
- static int b;
- const int c;
- static const int d=4;
- public:
- Test():c(3) //a(1)或者在初始化清單裡初始化
- {
- a=1;
- }
- };
- int Test::b=2;
- void main()
- {
- Test t;
- }
2. 類成員變量初始化順序
C++
有如下幾條:
1構造函數初始化清單的變量優先于構造函數(至少明顯的寫在前面) (若都在初始化清單中初始化,則按聲明順序初始化,與初始化清單中的順序無關)
2靜态成員變量先于執行個體變量
3父類成員變量先于子類成員變量
4父類構造函數先于子類構造函數
舉一個例子:
[cpp] view plain copy
- #include <iostream>
- #include <string>
- using namespace std;
- class Test
- {
- public:
- Test(string n)
- {
- cout<<n<<endl;
- }
- };
- class Base
- {
- public:
- static Test* a;
- Test* b;
- Test* c;
- Base():b(new Test("b"))
- {
- c=new Test("c");
- }
- virtual ~Base()
- {
- if(a) delete a;//似乎是很欠妥的做法
- if(b) delete b;
- if(c) delete c;
- }
- };
- Test* Base::a=new Test("a");
- class Derived:Base
- {
- public:
- static Test* da;
- Test* db;
- Test* dc;
- Derived():db(new Test("db"))
- {
- dc=new Test("dc");
- }
- ~Derived()
- {
- if(da) delete da;//似乎是很欠妥的做法
- if(db) delete db;
- if(dc) delete dc;
- }
- };
- Test* Derived::da=new Test("da");
- void main()
- {
- Derived d;
- }
結果是:
a
da
b
c
db
dc
java和C#語言
1 類成員變量初始化先于類的構造函數
2 靜态成員變量先于執行個體變量
3 父類成員變量先于子類成員變量 (C#相反)
4 父類構造函數先于子類構造函數
1 類成員變量初始化先于類的構造函數
2 靜态成員變量先于執行個體變量
3 父類成員變量先于子類成員變量 (C#相反)
4 父類構造函數先于子類構造函數
舉一個java的例子:
[java] view plain copy
- class Base
- {
- public static Test a=new Test("a");
- public static Test b;
- public Test c=new Test("c");
- public Test d;
- static
- {
- b=new Test("b");
- }
- public Base()
- {
- d=new Test("d");
- }
- public static void main(String[] args) {
- new Derived();
- }
- }
- class Derived extends Base
- {
- public static Test da=new Test("da");
- public static Test db;
- public Test dc=new Test("dc");
- public Test dd;
- static
- {
- db=new Test("db");
- }
- public Derived()
- {
- dd=new Test("dd");
- }
- }
- class Test
- {
- public Test (String name) {
- System.out.println(name);
- }
- }
運作結果是:
a
b
da
db
c
d
dc
dd
a
b
da
db
c
d
dc
dd
C++ static、const和static const 以及它們的初始化
const定義的常量在超出其作用域之後其空間會被釋放,而static定義的靜态常量在函數執行後不會釋放其存儲空間。
static表示的是靜态的。類的靜态成員函數、靜态成員變量是和類相關的,而不是和類的具體對象相關的。即使沒有具體對象,也能調用類的靜态成員函數和成員變量。一般類的靜态函數幾乎就是一個全局函數,隻不過它的作用域限于包含它的檔案中。
在C++中,static靜态成員變量不能在類的内部初始化。在類的内部隻是聲明,定義必須在類定義體的外部,通常在類的實作檔案中初始化,如:double Account::Rate=2.25;static關鍵字隻能用于類定義體内部的聲明中,定義時不能标示為static
在C++中,const成員變量也不能在類定義處初始化,隻能通過構造函數初始化清單進行,并且必須有構造函數。
const資料成員 隻在某個對象生存期内是常量,而對于整個類而言卻是可變的。因為類可以建立多個對象,不同的對象其const資料成員的值可以不同。是以不能在類的聲明中初始化const資料成員,因為類的對象沒被建立時,編譯器不知道const資料成員的值是什麼。
const資料成員的初始化隻能在類的構造函數的初始化清單中進行。要想建立在整個類中都恒定的常量,應該用類中的枚舉常量來實作,或者static cosnt。
[cpp] view plain copy
- 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時,不能給他初值
[cpp] view plain copy
- class foo
- {
- public:
- foo():i(100){}
- private:
- const int i=100;//error!!!
- };
- //或者通過這樣的方式來進行初始化
- foo::foo():i(100)
- {}
2、類裡的static成員初始化:
類中的static變量是屬于類的,不屬于某個對象,它在整個程式的運作過程中隻有一個副本,是以不能在定義對象時 對變量進行初始化,就是不能用構造函數進行初始化,其正确的初始化方法是:
資料類型 類名::靜态資料成員名=值;
[c-sharp] view plain copy
- class foo
- {
- public:
- foo();
- private:
- static int i;
- };
- int foo::i=20;
- 這表明:
- 1、初始化在類體外進行,而前面不加static,以免與一般靜态變量或對象相混淆
- 2、初始化時不加該成員的通路權限控制符private、public等
- 3、初始化時使用作用域運算符來表明它所屬的類,是以,靜态資料成員是類的成員而不是對象的成員。
3、類裡的static cosnt 和 const static成員初始化
這兩種寫法的作用一樣,為了便于記憶,在此值說明一種通用的初始化方法:
[cpp] view plain copy
- class Test
- {
- public:
- static const int mask1;
- const static int mask2;
- };
- const Test::mask1=0xffff;
- const Test::mask2=0xffff;
- //它們的初始化沒有差別,雖然一個是靜态常量一個是常量靜态。靜态都将存儲在全局變量區域,其實最後結果都一樣。可能在不同編譯器内,不同處理,但最後結果都一樣。
這是一個完整的例子:
[cpp] view plain copy
- #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();//通過對象通路靜态成員函數
- }