C++ 深度解析教程(六)对象的构造、初始化列表的使用

十七、对象的构造(上)

1、问题:对象中成员变量的初始值是多少?

2、小实验:下面的类定义中成员变量i和j的初始值为什么?

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第1张图片

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

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第2张图片

3、对象的初始化

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

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第3张图片

  • 编程实验:初始化函数

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第4张图片

  • 存在的问题
    • initialize 只是一个普通函数必须显示调用
    • 如果未调用initialize函数,运行结果是不确定的

4、构造函数

  • C++中可以定义与类名相同的特殊成员函数
    • 这种特殊的成员函数叫做构造函数
      • 构造没有任何返回类型的声明
      • 构造函数在对象定义时自动被调用
  • 编程实验:构造函数初探

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第5张图片

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第6张图片 

5、小结

  • 每个对象在使用之前都应该初始化
  • 类的构造函数用于对象的初始化
  • 构造函数与类同名并且没有返回值
  • 构造函数在对象定义时自动被调用

十八、对象的构造(中)

1、构造函数

  • 带有参数的构造函数
    • 构造函数可以根据需要定义参数
    • 一个类中可以存在多个重载的构造函数
    • 构造函数的重载遵循C++重载的规则

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第7张图片

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

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第8张图片

  • 构造函数的自动调用

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第9张图片

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

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第10张图片

注意:初始化和赋值是完全不一样的。

  • 构造函数的调用
    • 一般情况下,构造函数在对象定义时被自动调用
    • 一些特殊情况下,需要手工调用构造函数
    • 如何创建一个对象数组?
      • 编程实验:构造函数的手动调用

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第11张图片

2、小实例

  • 需求:开发一个数组类解决原生数组的安全性问题
    • 提供函数获取数组长度
    • 提供函数获取数组元素
    • 提供函数设置数组元素

3、编程实验:数组类的实现

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第12张图片

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第13张图片

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第14张图片

4、小结

  • 构造函数可以根据需要定义参数
  • 构造函数之间可以存在重载关系
  • 构造函数遵循C++中重载函数的规则
  • 对象定义时会触发构造函数的调用
  • 在一些情况下可以手动调用构造函数

十九、对象的构造(下)

1、特殊的构造函数

  • 两个特殊的构造函数
    • 无参构造函数
      • 没有参数的构造函数
    • 拷贝构造函数
      • 参数为const class_name&的构造函数
  • 两个特殊的构造函数
    • 无参构造函数
      • 当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空
    • 拷贝构造函数
      • 当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数简单的进行成员变量的值复制
  • 编程实验:特殊的构造函数

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第15张图片

2、拷贝构造函数

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

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第16张图片

3什么时候需要进行深拷贝

  • 对象中有成员指代了系统中的资源
    • 成员指向了动态内存空间
    • 成员打开了外存中的文件
    • 成员使用了系统中的网络端口
    • ……
  • 问题分析

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第17张图片

  • 一般性原则:自定义拷贝构造函数必然需要实现深拷贝!!!

4、编程实验:数组类的改进

IntArray.c

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第18张图片

IntArray.h

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第19张图片

main.c

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第20张图片

5、小结

  • C++编译器会默认提供构造函数
  • 无参构造函数用于定义对象的默认初始状态
  • 拷贝构造函数在创建对象时拷贝对象的状态
  • 对象的拷贝有浅拷贝深拷贝两种方式
    • 浅拷贝使得对象的物理状态相同
    • 深拷贝使得对象的逻辑状态相同

二十、初始化列表的使用

1、问题:类中是否可以定义const成员?

2、小实验

  • 下面的类定义是否合法?
    • 如果合法ci 的值是什么存储在哪里

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第21张图片

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

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第22张图片

4、类成员的初始化

  • C++中提供了初始化列表对成员变量进行初始化
  • 语法规则

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第23张图片

  • 注意事项
    • 成员的初始化顺序与成员的声明顺序相同
    • 成员的初始化顺序初始化列表中的位置无关
    • 初始化列表先于构造函数的函数体执行

5、编程实验:初始化列表的使用

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第24张图片

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第25张图片

6、类中的const成员

  • 类中的const成员会被分配空间的(跟随初始化对象的存储位置)
  • 类中的const成员的本质是只读变量(不是常量)
  • 类中的const成员只能在初始化列表中指定初始值

编译器无法直接得到const成员的初始值,因此无法进入符号表成为真正意义上的常量。

7、编程实验:只读成员变量

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第26张图片

C++ 深度解析教程(六)对象的构造、初始化列表的使用_第27张图片

8、小插曲

  • 初始化与赋值不同
    • 初始化:对正在创建的对象进行初值设置
    • 赋值:对已经存在的对象进行值设置

9、小结

  • 类中可以使用初始化列表对成员进行初始化
  • 初始化列表先于构造函数体执行
  • 类中可以定义const成员变量
  • const成员变量必须在初始化列表中指定初值
  • const成员变量为只读变量

你可能感兴趣的:(C++,深度解析教程,c++,对象的构造,初始化列表的使用)