C++类和对象的成员函数
一、六大默认成员函数
1、对于默认成员函数的定义及概念
默认成员函数:用户没有显示实现,编译器自动生成的函数都称为成员函数
在一个类中,不管是不是空类,(在没有自己实现的情况下)这个类里面都会有六个默认的成员函数。六大默认成员函数有如下:
构造函数 | 析构函数 | 拷贝构造函数 | 赋值重载 | 取地址重载函数(非const) | 取地址重载函数(const) |
---|---|---|---|---|---|
初始化对象 | 清理对象 | 用同类对象初始化对象 | 把一个类赋值给类外一个类 | 编译器自动生成(可略) | 可略 |
二、构造函数
1、构造函数的作用
构造函数可以初始化一个对象,不是创建一个对象,假设需要对类里面的成员变量初始化,可以自己实现一个init来初始化,但是这样会很麻烦,因为每次的创建对象都要去调用init这个成员函数初始化,所以可以通过构造函数来方便初始化,以时间类为例:
如果写了构造函数:
这样就会很方便初始化类对象
2、构造函数的特性
1、构造函数和类名同名
2、构造函数只会在类定义的时候自动调用一次
3、构造函数没有返回值
4、构造函数支持重载
3、构造函数的函数重载
构造函数支持函数重载,可以重载(date类为例)为:
无参构造
有参构造
定义出来的类会自动调用有参或者无参的构造函数
4、默认的构造函数
对于无参的构造函数、全缺省的构造函数、编译器自动生成的构造函数,都称为默认的构造函数
5、默认生成的构造函数会带来的影响
对于一个date类来说,里面的成员变量都是内置类型,那么默认生成的构造函数会给这些内置类型一个随机值,如果在一个类中的成员变量中有一个自定义的成员的时候,如若这个自定义成员没有调用他自己的构造函数,那肯定会给随机值,但是这时候给了随机值会变得不好操控这个类中的自定义类型,所以对于一个类中有自定义类型的时候,这个自定义类型需要写构造函数。
当写了这个自定义类型的构造函数:
tisp:这里的Time的构造函数,直接在构造函数里对类成员赋值,是C++11的一个补丁
三、析构函数
1、析构函数的的作用
当一个类的生命周期结束的时候,这个类会自动调用析构函数,对类中的资源进行清理,而不是销毁这个类对象,销毁这个对象大多数和函数栈帧有关。
假设一个类没有设计资源申请,析构函数写不写的意义都是不大的,如果涉及到资源申请的时候没有一个析构函数对这款资源清理的话就会造成内存泄漏等问题。
假设一个类中在堆区申请了一块资源(内存):
2、析构函数的特征
1、析构函数的形式:~类(),以date类为例: ~date()
2、析构函数无参数,无返回值
3、一个类只能有一个析构函数,即析构函数无法重载
4、对象生命周期结束的时候,编译器自动调用析构函数
3、对于类中自定义类型的析构函数
假设date类中有个Time类,那肯定是要保证date调用析构函数后,再调用Time的析构函数:
四、拷贝构造函数
1、拷贝构造函数的作用
拷贝构造函数用于构造一个还没有创建的对象:
//假设这个创建了一个date d1
date d1(2022,2,05);
//然后创建一个新的对象date d2
date d2(d1);//这里就用到了拷贝构造函数
2、拷贝构造函数的特征
1、拷贝构造函数是构造函数的一种重载形式
2、拷贝构造的参数只有一个且这个参数被const修饰的类对象的引用例:date(const date& d),要是不是传引用编译器会报错
3、拷贝构造函数没有返回值
如果不穿引用为什么会报错,因为要是传值的话,会导致无穷递归的现象:
3、拷贝构造函数的一写常见问题
1、拷贝构造函数要是在没有自己定义的时候,编译器会自动生成一个,而这个自己生成的拷贝构造函数,只能实现内置类型的浅拷贝(值拷贝),而自定义类型会调用拷贝构造函数完成拷贝。
2、如果在没有资源申请的时候完全可以使用默认生成的拷贝构造函数,如果发生了资源申请的时候,没有写拷贝构造函数的时候那可就会发生很严重的问题:
申请资源不写拷贝构造:
申请资源写拷贝构造深拷贝:
拷贝构造的时候_p的地址空间对于两个类来说都是不一样的
五、赋值重载函数
1、赋值重载函数的作用
1、可以构造新创建的对象。
2、可以给一个旧的对象重新赋值。
2、赋值重载函数的特征
1、参数列表是一个const修饰的类的引用
2、返回值是*this
3、返回类型是类的引用
4、还要检测不能自己给自己赋值
3、赋值重载函数的一些常见问题
1、要是再涉及到空间资源分配的情况下,自己没有写赋值重载函数的话,会导致空间丢失的问题,因为默认生成的赋值重载函数实现的是浅拷贝,例:
错误分析:
六、对拷贝构造函数和赋值重载函数的总结
1、这两个内置函数,一定要主要资源申请时候的问题。
2、拷贝构造使用的场景:
(1)、对一个新创建的对象初始化时。
(2)、函数形参是类的时候。
(3)、返回值是类返回时。
3、赋值重载函数使用的场景:
(1)、当使用赋值运算符给一个已经初始化的对象赋值时,会调用赋值运算符重载。
(2)、当对象作为另一个对象的参数出现在赋值表达式中时,也会调用赋值运算符重载。例如:A3=A2+A1