c++ (5)- 类 构造函数和析构函数
1.类的声明和类的实现分开
1.1 类的声明和类的实现在一起的实例
很简单的方法,没有使用复杂的while循环语句或者for等等语句,正常情况下项目开发情况下的声明和实现是分开的。
实例1:类的声明和实现在一起

实例2:类的声明和实现在分开,声明写在“.h”文件中,实现写在“.cpp”中
可以有两种方法可以添加“.h”“.cpp”文件
方法1:直接自己创建;
方法2:使用IDE的自动创建功能



类的声明:

类的实现:需要注意的是:a.使用了域“MyTeacher::”;b.此代码是写在了类的内部,不是类的外部;

类的调用:可以使用打断点的方法,看到在执行的时候从main跳到了“MyTeacher.cpp”中执行了代码;

2.面向对象的封装-长方体问题
2.1 使用全局函数
判断两个长方体的体积是否相等,使用全局函数的方法

2.2 使用成员函数
2.2.1 面向过程的写法
这种写法是一种假的写法

2.2.2 面向对象的写法


3.类的前置声明

4.面向对象的封装-圆和点的问题
案例 2 设计一个圆形类( AdvCircle),和一个点类( Point),计算点在圆内部还是圆外
即:求点和圆的关系(圆内和圆外)

调用:

5.构造函数和析构函数
5.1 构造函数和析构函数demo
- 说明1:在查看构造函数和析构函数的调用过程,可以使用小技巧,使用中间函数objplay()在中间进行构造对象,在调用结束之后释放对象,然后调用析构函数;
说明2:注意, 类的数据成员是不能在声明类时初始化的。


【说明】
1.C++编译器默认会自动调用无参数的构造函数,前提是开发人员没有亲自手动调用含有参数的构造函数;

2.调用构造函数有三种方法:


5.2 构造函数
构造函数作用:完成对属性的初始化工作

5.3 有参构造函数
说明:
1.实质:在61行的等号的右边的括号里,实质是逗号表达式,c++编译器在执行的时候并非是要执行两个参数的构造函数,必须注意;"括号"
2.逗号表达式:实质最后调用的是逗号表达式的最后一个值,是“4”,而不是“3”;

5.4 有参构造函数的3种调用方法
这三种方法都比较常用,其中最后一种方法中有个一匿名对象的问题;在后面会进行讲解;

5.5 对象的初始化和赋值的操作
注意:对象的初始化和赋值操作是两个不同的操作,千万不要搞错了,有很多人在此处认识不够。

6.拷贝(赋值)构造函数
6.1 不使用拷贝构造函数显示调用
这样调用会非常的麻烦和繁琐

6.2 拷贝构造函数的调用时机
6.2.3 第一种调用时机
使用拷贝构造函数给开发人员提供了一种轻松修改对象的内容的方法;

6.2.4 第二种调用时机

【特别说明】在使用赋值等号操作符时,不会调用拷贝构造函数;只是使用了操作符“=”;

6.2.5 第三种调用场景


6.2.6 第四种调用场景-关于匿名对象的去和留

会调用下面的拷贝构造函数





接匿名对象的方法1:使用此方法则匿名对象直接成为了有名字的正式对象;

接匿名对象的方法2:使用此方法则赋值结束之后会把匿名对象析构掉;


7.构造函数的调用规则

8.构造析构阶段性总结

9.浅拷贝问题
9.1 浅拷贝问题的引出

9.2 浅拷贝的内存示意图
【说明】在拷贝obj2的时候,只是拷贝了内存的地址0xa11,之后还是指向同一个“堆”内存,是浅拷贝;并没有再次分配内存再次拷贝数据;
导致在析构的时候释放了两次内存空间;

9.3 浅拷贝出现问题的解决办法-深拷贝
图中的蓝色线,各自开辟空间;自己动手写拷贝构造函数


【特别】成员变量的命名


9.4 赋值问题中的深拷贝
【说明】如果要解决下面的问题,必须重载“等号操作符”,执行深拷贝;

【特别说明】这样也会存在内存泄漏的问题;被赋值后的堆内存中的obj3会内存泄漏;

10.初始化成员列表
10.1 出现的问题
【说明】出现问题的原因是B中的成员变量A没有合适的构造函数;


【测试】出现问题的原因是B中的成员变量A没有合适的构造函数;为B类提供了构造函数仍然报错;

10.2 初始化列表
【说明】在初始化列表的后面,除了可以初始化带A类的成员变量,当然也可以初始化其他的成员变量,比如此处的b1,b2;

同样的写法也是可以的:将重载的构造函数中将单独的参数“m”“n”传递给a1(m),a(n);也都是可以的;


10.3 调用顺序
【结论】结论很重要



10.4 const 初始化
【说明】如果初始化列表中有const修饰的成员变量,则必须初始化赋值



11.强化训练
11.1 构造和析构的调用关系
【说明】考虑代码执行的调用顺序:

结论:

11.2 匿名对象的生命周期-1
【说明】匿名对象的生命周期主要是看“如何接受”该匿名对象;
此处没有接收该匿名对象,所以直接就“析构”了;

11.3 匿名对象的生命周期-2
如果有人接的话,就不会直接调用析构函数了,需要等待return0 之后才会调用析构

11.4 构造中调用构造函数
【说明】最后执行结果的c的值是一个乱码;
因为匿名对象的没有被接收,直接析构掉了;
内部构造函数与外部的构造函数没有关系,所以是乱码;
【注意】在构造函数中调用构造函数一种危险的行为;


浙公网安备 33010602011771号