初始化列表(上)
类中是否可以定义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
", 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
", 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
", 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
", 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()
");
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
", 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()
");
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
", t.getCI());
49
50 t.setCI(10);
51
52 printf("t.ci = %d
", t.getCI());
53
54 return 0;
55 }
初始化与赋值不同
初始化:对正在创建的对象进行初值设置
赋值:对已存在的对象进行值设置
小结:
类中可以使用初始化列表对成员进行初始化
初始化列表先于构造函数体执行
类中可以定义const成员变量
const成员变量必须在初始化列表中指定初值
const成员变量为只读变量