C++ 关于类与对象(中篇) 类的6个默认成员函数 详解

server/2024/11/14 13:35:47/

1.类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下 6 个默认成员 函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

2.构造函数

构造函数 是一个 特殊 成员函数 名字与类名相同 , 创建类类型对象时由编译器自动调用 ,以保证
每个数据成员都有 一个合适的初始值,并且 在对象整个生命周期内只调用一次
class Date
{
public:void Init(int year, int month, int day){
_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();return 0;
}
对于 Date 类,可以通过 Init 公有方法给对象设置日期,但是每次都调用函数初始化太麻烦了,这里我们介绍使用构造函数。

特性

构造函数 特殊 的成员函数,不能以常规的情况理解,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是 初始化对象
其特征如下:
1. 函数名与类名相同
2. 无返回值。 不需要写(void)
3. 对象实例化时编译器 自动调用 对应的构造函数。
4. 构造函数可以 重载
5. 如果类中没有显式定义构造函数,则 C++ 编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
6. C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即: 内置类型成员变量在 类中声明时可以给默认值。
7. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

构造函数的使用

1.无参,自动调用

#include<iostream>
#include<assert.h>
using namespace std;class Date
{
public:Date(){cout << "Date()" << endl;_year = 1;   _month = 1;_day = 1;}void Print(){//cout << this << endl;cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;   // 声明int _month;int _day;
};
int main()
{Date d1;    d1是一个对象,调用无参构造函数,无参数调用时不能加()d1.Print();return 0;
}

对象实例化时编译器自动调用对应的构造函数。无参数调用时不能加()

2.含参数调用,自动调用

#include<iostream>
#include<assert.h>
using namespace std;class Date
{
public:Date(int year, int month, int day)   也可以写形参,传参调用{_year = year;_month = month;_day = day;}void Print(){//cout << this << endl;cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;   // 声明int _month;int _day;
};
int main()
{Date d2(2023, 7, 20); d2是一个对象含参数调用构造函数 必须这样写,规定就是参数写在对象的后面d2.Print();return 0;
}

含参数调用构造函数 必须这样写,d2是一个对象规定就是参数写在对象的后面

d1对象使用构造函数和d2对象使用构造函数对比

3.全缺省形式的构造函数

#include<iostream>
#include<assert.h>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1)//把上面两种形式的构造函数合并//写成全缺省函数{_year = year;_month = month;_day = day;}void Print(){//cout << this << endl;cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;   // 声明int _month;int _day;
};
int main()
{Date d1;d1.Print();Date d2(2023, 7, 20);//必须这样写,规定就是参数写在对象的后面d2.Print();Date d3(2023);d3.Print();Date d4(2023, 7);d4.Print();return 0;
}

4.如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

不定义构造函数,编译器是否自动生成?

class Date
{
public:void Print(){//cout << this << endl;cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "~Date()" << endl;}private:int _year; //= 1;   // 声明给的缺省值int _month; //= 1;int _day; //= 1;
};int main()
{// 构造函数,也是默认成员函数,我们不写,编译器会自动生成Date d1;d1.Print();return 0;
}

生成了随机值,使用了编译器自动生成的构造函数。

5.关于编译器生成的默认成员函数 || 默认构造函数

不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用?

内置类型和自定义类型:

解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型如:int/char...,指针等等自定义类型就是我们使用class/struct/union等自己定义的类型。

看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员调用的它的默认成员函数。

class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}

6.C++11 中针对内置类型成员,内置类型成员变量在类中声明时可以给默认值

当没有自定义构造函数时,如果在内置类型成员声明中给了缺省值,调用编译器自动生成的构造函数时会把声明给的缺省值当成默认值使用,而不是给随机值。

class Date
{
public:void Print(){//cout << this << endl;cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "~Date()" << endl;}private:int _year = 1;    声明给的缺省值int _month = 1;int _day = 1;
};int main()
{构造函数,也是默认成员函数,我们不写,编译器会自动生成Date d1;d1.Print();return 0;
}

class Date
{
public:Date()    构造函数不全部内置类型的初始化,调用构造函数时会使用内置类型声明给的的缺省值做默认值{_month = 2;_day = 2;}void Print(){//cout << this << endl;cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "~Date()" << endl;}private:int _year = 1;    声明给的缺省值int _month = 1;int _day = 1;
};int main()
{构造函数,也是默认成员函数,我们不写,编译器会自动生成Date d1;d1.Print();return 0;
}

7.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

注意:无参构造函数、全缺省构造函数我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。总结:不传参的就是默认构造函数。

3.析构函数

概念:
通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的?
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由
编译器完成的。而 对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

特性:

析构函数 是特殊的成员函数,其 特征 如下:
1. 析构函数名是在类名前加上字符 ~
2. 无参数无返回值类型。
3. 个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。
4. 对象生命周期结束时, C++ 编译系统系统自动调用析构函数。
5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如 Stack类。

自动调用析构函数示例

从执行结果和调试窗口都观察到编译器会自动调用析构函数销毁申请的资源

没有申请资源时,例如日期类,不需要写析构函数,没有可销毁的资源

3. 个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。


http://www.ppmy.cn/server/141869.html

相关文章

图论导引 - 第三章 第四节 - 11/13

相关算法 在本节中&#xff0c;我们简要描述与本章相关的三个问题——最短路径问题、中国邮递员问题和旅行商问题。 最短路径问题可以通过一种高效算法来解决&#xff0c;即通过一个有限的、逐步执行的程序能快速得出解决方案。邮递员问题只考虑一种特殊情况。旅行商问题&…

半导体企业如何利用 Jira 应对复杂商业变局?

以下是一篇关于如何利用 Jira 构建半导体企业数字化研发管理蓝图的文章。借鉴了 ONES 案例中的思路&#xff0c;并结合了 Jira 的特点&#xff0c;为半导体企业在复杂商业环境下进行数字化转型提供支持&#xff1a; 半导体企业如何利用 Jira 应对复杂商业变局&#xff1f; 在全…

qt QFrame详解

1、概述 QFrame是Qt框架中用于提供框架或边框的控件&#xff0c;主要用于在图形用户界面&#xff08;GUI&#xff09;中创建框架&#xff0c;并提供各种边框样式和功能。它是Qt中一个基础的容器类&#xff0c;也是许多基础控件的基类&#xff0c;可以被QLCDNumber、QToolBox、…

一则有意思的AI错误

豆包AI回复错误记录 提问过程完整截图 首次询问 这个回答是错误的 两次追问 第一次提出质疑后它的回答还是错误的&#xff0c;第二次说明自己的判断之后它的回答才修正过来。 询问代码如下 #define MAX_RT_MEM 1024*1024*32 void * rt_mem_space; if (rt_mem_space NULL)…

C++,STL 053(24.11.13)

内容 map容器的插入操作。 运行代码 #include <iostream> #include <map>using namespace std;void printMap(map<int, int> &m) {for (map<int, int>::iterator it m.begin(); it ! m.end(); it){cout << "key " << it…

2025年入门深度学习或人工智能,该学PyTorch还是TensorFlow?

随着2025应用人工智能和深度学习技术的举世泛气&#xff0c;还在迷茫于该选择哪个深度学习框架吗&#xff1f;PyTorch和TensorFlow是并立于深度学习世界两座巨塔&#xff0c;但是越来越多人发现&#xff0c;在2025年&#xff0c;PyTorch似乎比TensorFlow更为流行和被接受。下面…

webpack指南

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;webpack篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来webpack篇专栏内容:webpack-指南 概念 中文&#xff1a; webpack | webpack中文文档 | webpack中文网 英文&…

【SpringBoot】黑马大事件笔记-day3

目录 文章管理部分 自定义注解校验 注解的概念 元注解 规定约束的注解 分页查询 OSS文件上传 获取AccessKey 上期回顾&#xff1a; 【SpringBoot】 黑马大事件笔记-day1 【SpringBoot】 黑马大事件笔记-day2 文章管理部分 自定义注解校验 先来看一下接口文档了解需求&#xff…