外观
06.对象的构造、初始化列表的使用
约 1854 字大约 6 分钟
C++编程语言对象的构造个人
2022-06-15
十七、对象的构造(上)
1、问题:对象中成员变量的初始值是多少?
2、小实验:下面的类定义中成员变量i和j的初始值为什么?

编程实验:成员变量的初始值

3、对象的初始化
从程序设计的角度,对象只是变量,因此:
- 在栈上创建对象时,成员变量初始为随机值
- 在堆上创建对象时,成员变量初始为随机值
- 在静态存储区(全局、static)创建对象时,成员变量初始为0值
生活中的对象都是在初始化后上市的
初始状态(出厂设置)是对象普遍存在的一个状态
问题:程序中如何对一个对象进行初始化?
一般而言,对象都需要一个确定的初始状态
解决方案
- 在类中提供一个public的 initialize函数
- 对象创建后立即调用initialize函数进行初始化

- 编程实验:初始化函数

- 存在的问题
- initialize 只是一个普通函数,必须显示调用
- 如果未调用initialize函数,运行结果是不确定的
4、构造函数
C++中可以定义与类名相同的特殊成员函数
- 这种特殊的成员函数叫做构造函数
- 构造没有任何返回类型的声明
- 构造函数在对象定义时自动被调用
- 这种特殊的成员函数叫做构造函数
编程实验:构造函数初探


5、小结
- 每个对象在使用之前都应该初始化
- 类的构造函数用于对象的初始化
- 构造函数与类同名并且没有返回值
- 构造函数在对象定义时自动被调用
十八、对象的构造(中)
1、构造函数
- 带有参数的构造函数
- 构造函数可以根据需要定义参数
- 一个类中可以存在多个重载的构造函数
- 构造函数的重载遵循C++重载的规则

- 友情提醒
- 对象定义和对象声明不同
- 对象定义 - 申请对象的空间并调用构造函数
- 对象声明 - 告诉编译器存在这样一个对象

- 构造函数的自动调用

- 编程实验:带参数的构造函数

注意:初始化和赋值是完全不一样的。
- 构造函数的调用
- 一般情况下,构造函数在对象定义时被自动调用
- 一些特殊情况下,需要手工调用构造函数
- 如何创建一个对象数组?
- 编程实验:构造函数的手动调用

2、小实例
- 需求:开发一个数组类解决原生数组的安全性问题
- 提供函数获取数组长度
- 提供函数获取数组元素
- 提供函数设置数组元素
3、编程实验:数组类的实现



4、小结
- 构造函数可以根据需要定义参数
- 构造函数之间可以存在重载关系
- 构造函数遵循C++中重载函数的规则
- 对象定义时会触发构造函数的调用
- 在一些情况下可以手动调用构造函数
十九、对象的构造(下)
1、特殊的构造函数
两个特殊的构造函数
无参构造函数
- 没有参数的构造函数
拷贝构造函数
- 参数为const class_name&的构造函数
两个特殊的构造函数
无参构造函数
- 当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空
拷贝构造函数
- 当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制
编程实验:特殊的构造函数

2、拷贝构造函数
拷贝构造函数的意义
兼容C语言的初始化方式
初始化行为能够符合预期的逻辑
浅拷贝
- 拷贝后对象的物理状态相同(内存地址相同,所对应的值自然相同,见下面示例)
深拷贝
- 拷贝后对象的逻辑状态相同(内存地址不同,所对应的值相同,见下面示例)
编译器提供的拷贝构造函数只进行浅拷贝!
编程实验:对象的初始化

3、什么时候需要进行深拷贝?
对象中有成员指代了系统中的资源
- 成员指向了动态内存空间
- 成员打开了外存中的文件
- 成员使用了系统中的网络端口
- ……
问题分析

- 一般性原则:自定义拷贝构造函数,必然需要实现深拷贝!!!
4、编程实验:数组类的改进
IntArray.c

IntArray.h

main.c

5、小结
- C++编译器会默认提供构造函数
- 无参构造函数用于定义对象的默认初始状态
- 拷贝构造函数在创建对象时拷贝对象的状态
- 对象的拷贝有浅拷贝和深拷贝两种方式
- 浅拷贝使得对象的物理状态相同
- 深拷贝使得对象的逻辑状态相同
二十、初始化列表的使用
1、问题:类中是否可以定义const成员?
2、小实验
- 下面的类定义是否合法?
- 如果合法,ci 的值是什么,存储在哪里?

3、编程实验:类中的const成员


4、类成员的初始化
- C++中提供了初始化列表对成员变量进行初始化
- 语法规则

- 注意事项
- 成员的初始化顺序与成员的声明顺序相同
- 成员的初始化顺序与初始化列表中的位置无关
- 初始化列表先于构造函数的函数体执行
5、编程实验:初始化列表的使用


6、类中的const成员
- 类中的const成员会被分配空间的(跟随初始化对象的存储位置)
- 类中的const成员的本质是只读变量(不是常量)
- 类中的const成员只能在初始化列表中指定初始值
编译器无法直接得到const成员的初始值,因此无法进入符号表成为真正意义上的常量。
7、编程实验:只读成员变量


8、小插曲
- 初始化与赋值不同
- 初始化:对正在创建的对象进行初值设置
- 赋值:对已经存在的对象进行值设置
9、小结
- 类中可以使用初始化列表对成员进行初始化
- 初始化列表先于构造函数体执行
- 类中可以定义const成员变量
- const成员变量必须在初始化列表中指定初值
- const成员变量为只读变量
