初始化列表(上)
類中是否可以定義const成員?
下面的類定義是否合法?
如果合法,ci的值是什么,存儲在哪里?
class Test
{
private:
const int ci;
public:
int getCI() { return ci; }
}
編程實驗:類中是否可以存在const成員?
1 #include <stdio.h>
2
3 class Test 4 { 5 private: 6 const int ci; 7 public:12 int getCI() 13 { 14 return ci; 15 } 16 }; 17
18
19 int main() 20 {
25 return 0; 26 }
上面的程序可以編譯成功,說明類中可以定義const成員。
接下來再看:
1 #include <stdio.h>
2
3 class Test 4 { 5 private: 6 const int ci; 7 public:
12 int getCI() 13 { 14 return ci; 15 } 16 }; 17
18
19 int main() 20 { 21 Test t; 23 printf("t.ci = %d\n", t.getCI()); 24
25 return 0; 26 }
編譯時會出錯:
21:error: structure 't' with uninitialized const members
在類中可以定義const成員變量,但是通過類來定義對象的時候就會報錯。提示有未初始化的const成員,因此面臨的問題變成了如何初始化一個類中的const成員。
解決方式:可以在類中添加構造函數,是否可行呢?可以試試
1 #include <stdio.h>
2
3 class Test 4 { 5 private: 6 const int ci; 7 public: 8 Test() 9 { 10 ci = 10; 11 } 12 int getCI() 13 { 14 return ci; 15 } 16 }; 17
18
19 int main() 20 { 21 Test t; 22
23 printf("t.ci = %d\n", t.getCI()); 24
25 return 0; 26 }
編譯又出錯了,提示:
8: error: uninitialized member 'Test::ci' with 'const' type 'const int'
10:error: assigment of read-only data-member 'Test::ci'
ci 是只讀的,不能放在賦值號的左邊。
可以得出一個結論,如果要初始化const成員變量,就得在第8行進行。那么在第8行如何進行呢?此時初始化列表就需要閃亮登場了。
C++中提供了初始化列表對成員變量進行初始化
語法規則
ClassName::ClassName() :
m1(v1), m2(v1,v2), m3(v3)
{
// some other initialize operation
}
1 #include <stdio.h>
2
3 class Test 4 { 5 private: 6 const int ci; 7 public: 8 Test() : ci(10) 9 { 10
11 } 12 int getCI() 13 { 14 return ci; 15 } 16 }; 17
18
19 int main() 20 { 21 Test t; 22
23 printf("t.ci = %d\n", t.getCI()); 24
25 return 0; 26 }
初始化列表(中)
注意事項:
成員的初始化順序與成員的聲明順序相同
成員的初始化順序與初始化列表中的位置無關
初始化列表先於構造函數的函數體執行
舉例說明:
ClassName::ClassName() :
m1(v1),m2(v1,v2),m3(v3)
{
}
在初始化列表中m1,m2,m3的順序是這樣排列的,但是這並不意味着m1先於m2進行初始化,m2先於m3進行初始化。
因為:成員的初始化順序與成員的聲明順序相同,與初始化列表中的位置無關
實驗分析:
1 #include <stdio.h>
2
3 class Value
4 {
5 private:
6 int mi;
7 public:
8 Value(int i)
9 {
10 printf("i = %d\n", i);
11 mi = i;
12 }
13 int getI()
14 {
15 return mi;
16 }
17 };
18
19 class Test
20 {
21 private:
22 Value m2;
23 Value m3;
24 Value m1;
25 public:
26 Test() : m1(1), m2(2), m3(3)
27 {
28 printf("Test::Test()\n");
29 }
30 };
31
32
33 int main()
34 {
35 Test t;
36
37 return 0;
38 }
該實驗表明:
類中的成員變量必須通過初始化列表來進行初始化(說的是初始化,不是賦值哦)
成員的初始化順序與初始化列表中的位置無關
初始化列表先於構造函數的函數體執行
初始化列表(下)
類中的const成員
類中的const成員會被分配空間的
類中的const成員的本質是只讀變量
類中的const成員只能在初始化列表中指定初始值
編譯器無法直接得到const成員的初始值,因此無法進入符號表成為真正意義上的常量。
既然是會被分配空的,那么分配的空間是在哪里呢?
類中const成員分配的空間是和整個類對象所分配的空間是一致的,也就是說,如果當前的對象在棧上分配空間,那么const成員就在棧上分配空間。如果當前的對象在堆上分配空間,那么當前的對象就在堆上分配空間。
只讀變量成員試驗
1 #include <stdio.h>
2
3 class Value
4 {
5 private:
6 int mi;
7 public:
8 Value(int i)
9 {
10 printf("i = %d\n", i);
11 mi = i;
12 }
13 int getI()
14 {
15 return mi;
16 }
17 };
18
19 class Test
20 {
21 private:
22 const int ci;
23 Value m2;
24 Value m3;
25 Value m1;
26 public:
27 Test() : m1(1), m2(2), m3(3), ci(100)
28 {
29 printf("Test::Test()\n");
30 }
31 int getCI()
32 {
33 return ci;
34 }
35 int setCI(int v)
36 {
37 int* p = const_cast<int*>(&ci); //將const屬性去掉,就用const_cast這個屬性。
38
39 *p = v;
40 }
41 };
42
43
44 int main()
45 {
46 Test t;
47
48 printf("t.ci = %d\n", t.getCI());
49
50 t.setCI(10);
51
52 printf("t.ci = %d\n", t.getCI());
53
54 return 0;
55 }
初始化與賦值不同
初始化:對正在創建的對象進行初值設置
賦值:對已存在的對象進行值設置
小結:
類中可以使用初始化列表對成員進行初始化
初始化列表先於構造函數體執行
類中可以定義const成員變量
const成員變量必須在初始化列表中指定初值
const成員變量為只讀變量