C++类与对象(中上)

目录

类的6个默认构造函数

构造函数

概念

特性

默认的构造函数

编译器默认生成的构造函数

析构函数

概念

特性

编译器默认生成的析构函数


类的6个默认构造函数

C++类与对象(中上)_第1张图片

构造函数

概念

对于以下栈类(简单模拟):C++类与对象(中上)_第2张图片 定义出对象s后,首先需要调用初始化函数Init(),把对象s初始化。如果忘记调用该方法,进行一些入栈等操作,就会导致编译器报错,但是每次定义对象都要是使用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?

构造函数是一个特殊的成员函数,无返回值(注意不是void),名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员 都有 一个合适的初始值,并且在对象的生命周期内只调用一次。
那么就可以对于以上栈类做如下优化:
C++类与对象(中上)_第3张图片

 以上代码中,创建出对象s后,直接把需要申请的空间数放在对象后的括号中,编译器就会自动调用构造函数初始化对象。这样做更加高效。

特性

构造函数的主要任务并不是开空间创建对象,而是初始化对象。其特征如下:
1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。
5.如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
例如以下日期类:
C++类与对象(中上)_第4张图片 有两个构造函数,说明可以重载,也可以有多个,看需求写不同的构造函数。

默认的构造函数

默认的构造函数有三种:

1.我们不写,编译器默认生成的。如下日期类:C++类与对象(中上)_第5张图片观察以上结果,打印出来的年、月、日都是一些随机值,这样看来,好像并没有调用自动生成的构造函数,但事实是已经调用了,只是这个自动生成的构造函数没有处理这些基本类型的参数(例如int、char)。

2.无参数的构造函数。如下日期类:C++类与对象(中上)_第6张图片通过观察以上运行结果,自定义的无参构造函数确实被调用了,但是年、月、日还是随机值,因为在自定义的构造函数中,也没有对它们进行处理。

3.全缺省参数的构造函数。如下日期类:C++类与对象(中上)_第7张图片这一次缺省参数的默认值就起作用了,对年、月、日进行了相应赋值。

总结一下:默认的构造函数都有一个特征,就是在创建出对象后不用在对象后加括号,此时调用的就是默认的构造函数。

注意:默认的构造函数只能存在一个。

编译器默认生成的构造函数

关于编译器生成的默认成员函数,很多童鞋会有疑惑:在我们不实现构造函数的情况下,编译器会生成 默认的构造函数。但是看起来默认构造函数又没什么用?d1对象调用了编译器生成的默认构造函数,但 是d对象year/month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数没有什么卵 用??
解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语法已经定义好的类型如
int/char...,自定义类型就是我们使用class/struct/union自己定义的类型,看看下面的程序,就会发现 编译器生成默认的构造函数会对自定类型成员aa调用的它的默认成员函数
C++类与对象(中上)_第8张图片

观察上面代码的运行结果,"A类的默认构造函数被调用"这句话在一开始就被打印了,这说明在创建对象d1时,d1调用了编译器自动生成的默认构造函数,而这个默认生成的构造函数并不是什么都没做,它调用了自定义类型aa的默认构造函数。

总结:编译器默认生成的构造函数对基本类型不处理,对自定义类型调用它的默认构造函数。

析构函数

概念

析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

特性

析构函数是特殊的成员函数,其特征如下:

1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值。
3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
析构函数相比较构造函数,就简单许多了,先来验证析构函数是否自动调用:
C++类与对象(中上)_第9张图片

因为析构函数是在对象生命周期结束后自动调用,也就是说在main函数调用完成后才会调用析构函数,此时如果直接按F5执行完程序,是观察不到现象的。应该在 return 0;语句处打上断点,然后直接F5让程序执行到最后,在按F11,此时就会发现代码会去调用析构函数。

以上代码中的析构函数并没有什么意义,因为此时没有需要被清理的资源。以下类中的析构函数就有意义了:C++类与对象(中上)_第10张图片

对于模拟出来的栈对象,很多时候在结束时会忘记释放在堆上申请出来的空间,把将释放空间的代码放在析构函数中就解决了这一问题。

编译器默认生成的析构函数

如果自己不写,编译器会默认生成析构函数,但是这个默认生成的析构函数会做什么?

编译器默认生成的析构函数,对基本类型不处理,对自定义类型会去调用它的析构函数。这一点和默认生成的构造函数很像。来看以下代码就明白了:C++类与对象(中上)_第11张图片

当d1对象生命周期结束后,它调用了自己的析构函数,然后这个析构函数调用了自定义类型对象aa的析构函数。

最后来看下面这种情况,两个对象析构先后的问题:

C++类与对象(中上)_第12张图片

 

你可能感兴趣的:(C++类与对象,构造函数,析构函数,c++,visual,studio)