第20课 初始化列表的使用

初始化列表(上)

类中是否可以定义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成员变量为只读变量

posted @ 2019-11-06 22:32  一代枭雄  阅读(547)  评论(0编辑  收藏  举报