【C++】-关于类和对象的默认成员函数(中)-构造函数和析构函数

news2024/11/23 15:21:42

💖作者:小树苗渴望变成参天大树
❤️‍🩹作者宣言:认真写好每一篇博客
💨作者gitee:gitee
💞作者专栏:C语言,数据结构初阶,Linux,C++
在这里插入图片描述

如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、类的6个默认成员函数
  • 二、案例引入
  • 三、构造函数
  • 四、析构函数
  • 五、总结


前言

从这篇开始我们才算是真正的步入类和对象的学习,在C++入门的时候,就已经说过,这是最难学的语言之一,在于它前期的门槛很高,学起来挺吃力的,所以我不打算把类和对象的重点放到一篇来讲,怕大家坚持不下去看完,所以我把中篇分好几篇来学,这样大家学起来也不会特别的吃力,今天我们就来讲解一下在类和对象的一组默认成员函数,学好着两个,对后面其他的默认函数学起来也有很大的帮助,那让我们开始进入正文吧。


一、类的6个默认成员函数

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

在这里插入图片描述

二、案例引入

大家还记得我们在学习栈的时候,我写过一篇博客,是关于有效的括号这个题目,这个题目,我们有多处返回值.
在这里插入图片描述
大家看到每次返回的时候都要进行一次销毁,所以特别的麻烦,二有时候忘记的初始化,造成程序的崩溃,这题用我们目前学到的C++写和C语言差距不大,等学到后面的STL的时候才会特别的爽,我们先用C++把大致框架写出来:
在这里插入图片描述
我们将刚才的函数都封装在一个类中,注意这时候就不需要传地址了,因为类里面的成员变量在成员函数里面都是可以直接使用的。我们看判断函数里面怎么实现的:

在这里插入图片描述
大家看到几乎和C语言一样,所以优势不明显,这时候我们需要来讲解一下构造函数和析构函数:

构造函数:构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

其特征如下:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。

对于刚才的题目,我们把初始化函数直接改成构造函数:
在这里插入图片描述
这时候我们不需要写调用初始化函数编译器自动调用这个构造函数来实现初始化

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

其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数

我们把销毁函数直接写成析构函数:
在这里插入图片描述

在这里插入图片描述
最主要的是最后的差距就非常明显

通过着两个例子:让大家初步认识了构造函数和析构函数,可以帮你自动完成忘记的事,并且可以完成初始化的数据,对于这个例子的栈我给大家方出来,因为后面徽通过这个栈类来讲解构造和析构其他的知识点

栈类:

typedef int DataType;
class Stack
{
public:
 Stack(size_t capacity = 3)
 {
 _array = (DataType*)malloc(sizeof(DataType) * capacity);
 if (NULL == _array)
 {
 perror("malloc申请空间失败!!!");
 return;
 }
 _capacity = capacity;
 _size = 0;
 }
 void Push(DataType data)
 {
 // CheckCapacity();
 _array[_size] = data;
 _size++;
 }
 // 其他方法...
 ~Stack()
 {
 if (_array)
 {
 free(_array);
 _array = NULL;
 _capacity = 0;
 _size = 0;
 }
 }
private:
 DataType* _array;
 int _capacity;
 int _size;
};

这里面的其他操作函数我就不写了和插入类似,把构造和析构写上去。

在接下来重点讲解构造函数和析构函数

三、构造函数

大家刚才可以说值看到了构造函数的前 个特性,名字和类名相同,没有返回值,接下来介绍其他两个特性

我们来看一个日期类:
在这里插入图片描述
我们通过这个例子不难出来我们确实是自动调用了构造函数,大家看到了第 个特性。

在日常中,我们肯定不止一种初始化方式,这时候就要说到第 个特性,构造函数也可以重载。我们就以这个栈类来写一个函数重载的例子:这是一开始数组里面就有数据想要导到栈里面去
在这里插入图片描述
我们在日期类中写一个函数重载的构造函数:
在这里插入图片描述
对于有参数的需要在创建对象的时候去进行传参,因为他是一个特殊的函数,所以传参也是特殊的,创造者是这样规定的,所以大家不要想和普通函数一样的去调用。因为第一个没有进行初始化所以打印出来的都是随机值

在前面我大致讲了四个特性了,其实它还有要注意的点。

个特性:

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

我们来看看没有显示调用调用默认生成会发生什么:
在这里插入图片描述
按照以往的逻辑应该是把初始化为0,但是这里却没有任何变化,这里也是创造者设计的一个不好的地方,因为是默认生成的所以没办法像之前一样的在构造函数打印一些东西出来看看效果,既然这样,默认构造函数难道真的一点事都不干了吗??我们在来看一下:
在这里插入图片描述
大家看看我们加了一个自定义类型, 默认生成的构造函数对于内置类型(int double,char,指针等)不做处理,但是对于自定义类型,会调用它本身的构造类型

在这里插入图片描述

所以默认生成的构造函数还是有作用的。

第六个特性:无参的构造函数全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

我们来看具体例子:
在这里插入图片描述

对于语法这两个构造函数是可以具体存在的,但是在调用的时候会出现调用歧义,因为都不需要传参,所以不传参就可以调用的就是默认构造函数
所以这三个只能存在一个。

在C++11的时候就补了这个漏洞,可以在声明的时候个缺省值

class Date
{
private:
 // 基本类型(内置类型)
 int _year = 1970;
 int _month = 1;
 int _day = 1;
 // 自定义类型
 Time _t;
};

这里不是初始化,只是声明,这里给的都是默认值,在没有显示默认构造函数的时候,就会使用这里的缺省值给变量进行赋值,解决了随机值的问题,但之前的问题还保留在,你敢轻易的去修改,怕有人刚好用了这个随机值就麻烦了。但显示了构造函数,就不会使用这些缺省值

那我们什么时候应该写构造函数呢??

  1. 一般情况下,有内置类型成员,就需要自己写构造函数,有内置类型但有缺省值也可以不用写,看具体条件
  2. 都是构造函数不用写,他可以调用自己类的构造函数,但是自己类的构造函数还是需要我们自己写的,一切自定义类型追溯到最上面都是内置类型

在两个栈实现队列的时候是典型的不需要写构造函数,因为都是内置类型,刚兴趣的同学可以去力扣上做一下这道题

解决困惑:

==1.==在默认构造函数的时候,说过是不传参的就可以,和传参调用的格式一样,那我们时候这样调用可不可以:

Date d1();//无参
Date d2(20023,5,1)//有参

这样不久更好的理解了,为什么不可以呢?这样容易和函数的声明弄混,而第二个不会弄混

==2.==我们知道在编译器默认生成的构造函数的时候对内置类型不做处理,那为什么加了自定义类型就初始化了呢??

在这里插入图片描述
实际上这是编译器自己弄的,不是创造者弄的,在不同的编译器就会出现不同的情况,有vs2013的老铁可以试试去看看结果,本身会不会初始化的,不同的编译器可能有不同的处理方法。

==3.==大家发现调用的时候非常麻烦,有点人会说为什么不能这么调用:

d1.Date();
d1.Date(2023,5,1);

这个方法对我们学习起来很简单,但是这样调用和之前我自己写一个初始化函数调用有啥区别??所以创造者那么做肯定有他的道理

讲完构造函数,接下来讲的析构函数就简单很多,没有什么要特别注意的特性

四、析构函数

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

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数

析构函数也是编译器默认生成的,对于内置类型,编译器默认生成的析构函数不做处理,有自定义类型的时候,就会调用自定义类的析构函数,其余没啥要注意的点,因为少了重载而且无参数,就没啥改注意的地方,所以说析构函数还是比较好理解和掌握的

那什么时候不需要写析构函数呢?

  1. 一般情况下,有动态申请资源就需要显示写析构函数释放资源(栈是典型的例子)
  2. 没有动态申请就不需要写
  3. 释放资源的成员都是自定义类型,不需要写析构函数(用两个栈写一个队列)

五、总结

通过这篇学习大家应该了解构造函数和析构函数,他的重要性,和什么时候要写,以及怎么去使用,因为这个对于我们后面学习模拟STL很有帮助,不然后面你根本听不懂,所以这篇博客,大家一定要理解,尤其是默认生成的,他也是有工作要做的,希望大家能够明白,我们这篇知识点就讲到这里了,我们下篇再见

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/479613.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cadence(2):向导制作PCB封装

前提:软件版本 焊盘设计 :Pad Designer16.6PCB设计 :PCB Editor16.6 文章目录 LQFP64向导封装制作封装信息SMD焊盘制作添加焊盘库到PCB Editor新建工程LQFP64向导制作流程后续处理修改栅格大小。贴加1脚标识修改丝印线 总结 LQFP64向导封装制…

获取代码量(针对Pycharm IDEA)

Statistic 这是个一劳永逸,获取代码量的方法。 Beginning!(安装到使用可能都不需要5分钟) 附上Statistic的官网下载URL:Statistic - IntelliJ IDEs Plugin | Marketplacehttps://plugins.jetbrains.com/plugin/4509-statistic/v…

clion + opencv环境搭建

clion是一个jetbrains提供的c开发环境,和idea,pycharm等开发工具类似,界面有很多相似的地方。 clion内置了一个mingw的编译环境,自带了gcc,g等命令,安装完clion之后,我们新建项目,它会使用内置的mingw环境。…

在KylinV10上使用DTS进行mysql8迁移至DM8

前言: MySQL 到 DM 的移植主要有以下几个方面的工作: 1.分析待移植系统,确定移植对象。2.通过数据迁移工具 DTS 完成常规数据库对象及数据的迁移。3.通过人工完成 MSQL 的移植。4.移植完成后对移…

从设计到产品

从设计到产品 最近上的一些课的笔记,从 0 开始设计项目的角度去看产品。 设计系统 设计系统(design system) 不是 系统设计(system design),前者更偏向于 UI/UX 设计部分,后者更偏向于实现部分。 个人觉得,前端开发与 UI/UX 设…

使用 ESP32 设计智能手表 – 第 1 部分制作表盘

相关设计资料下载ESP32 智能手表带心率、指南针设计资料(包含Arduino源码+原理图+Gerber+3D文件).zip 人们可以使用智能手表轻松快速地访问消息、警报、健康信息和其他高级信息。虽然智能手表作为独立设备在形式上是革命性的,但当与人们携带的其他设备(例如智能手机或平板…

作为一个大学生你应该知道的事情

作为一个大学生你应该知道的事情 大学生毕业去向 今天,我们不写技术,来谈一谈大学生的毕业现状: 以下内容为本人的一些观点和看法,仅限于沟通交流。 大学生毕业去向 大学生的毕业去向大致可以分为:就业、自由职业、慢…

Python之常用设计模式

1、 设计模式 2、接口 interface.py #! /usr/bin/env python # -*- coding: utf-8 -*- # Date: 2018/12/1# class Payment: # def pay(self, money): # raise NotImplementedErrorfrom abc import ABCMeta, abstractmethod# 接口 # class Payment(metaclassABCMet…

低频量化之 可转债 配债数据及策略 - 全网独家

目录 历史文章可转债配债数据 待发转债(进展统计)待发转债(行业统计)待发转债(5证监会通过,PE排序)待发转债(5证监会通过,安全垫排序)待发转债(5证…

JVM--一文精通

调整JVM堆内存 在确定JVM堆内存大小时,需要考虑以下因素: 应用程序的内存需求。操作系统和其他应用程序所需的内存。JVM的运行参数和GC算法。 根据通常的经验,可以将JVM最大堆内存设置为操作系统可用内存的约70%。也就是说,在1…

Kube-OVN组件

文章目录 介绍ovn架构kube-ovn架构kube-ovn数据流向软件版本及注意事项高可用部署安装kube-ovn运维查看Pod日志组件监控kubectl ko插件 网络相关 介绍 kube-ovn是基于ovn开发的。https://man7.org/linux/man-pages/man7/ovn-architecture.7.html ovn架构 组件说明&#xff1a…

PySide6/PyQT多线程之 信号与槽 / (Signal Slot)的高效利用

前言 PySide6/PyQT信号槽是一种事件处理方式,允许程序中的对象发送和接收信号。 在 PySide6/PyQT 精进的过程中,一定躲不开 信号和槽 这座大山,这是一个比较有意思的知识点: 初接触的看不懂,觉得复杂;看得…

【Linux】win10远程控制Linux服务器 - 内网穿透实现公网远程

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 前言 视频教程 1. ubuntu安装XRDP 2.局域网测试连接 3. Ubuntu安装cpolar内网穿透 4.cpolar公网地址测试访问 5.固定域名公网地址 [TOC] 转载自远程穿透文章:Wi…

Redis的两种持久化方案 RDB AOF

文章目录 1.RDB持久化1.1.执行时机1.2.RDB原理1.3.小结 2.AOF持久化2.1.AOF原理2.2.AOF配置2.3.AOF文件重写 3.RDB与AOF对比 Redis有两种持久化方案: RDB持久化AOF持久化 1.RDB持久化 RDB全称Redis Database Backup file(Redis数据备份文件&#xff09…

【三十天精通Vue 3】 第二十三天 Vue 3的错误处理详解

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 错误处理概览1. 错误处理的重要性2. Vue 3 中的错误…

EMS快递批量分析物流信息状况

众所周知“邮政快递”是在快递行业里面也是算一家行业龙头,中国邮政特快专递/EMS,邮政平邮小包,邮政挂件等,都是属于中国邮政集团,邮政速度快,价格也是比较实惠一家,所以很多产家或电商 、供应商…

大数据-玩转数据-FLINK快速上手

一、环境准备 ⚫系统环境为 Windows 10。 ⚫需提前安装 Java 11。 ⚫集成开发环境(IDE)使用 IntelliJ IDEA,具体的安装流程参见 IntelliJ 官网。 ⚫安装 IntelliJ IDEA 之后,还需要安装一些插件——Maven 和 Git。Maven 用来管理…

Java实现宿舍管理系统的设计与实现【附源码】

本科生毕业论文(设计) 宿舍管理系统的设计与实现 目 录 摘 要 I Abstract II 1 引言 1 1.1 研究背景 1 1.2 国内外研究现状 1 1.3 研究目的与意义 1 2 开发工具和相关技术 2 2.1 Eclipse 2 2.2 MySQL 2 2.3 Bootstrap 3 2.4 Tomcat 3 3 系统分析 3 3.1…

Java基础学习(11)

Java基础学习 一、集合进阶1.1 数据结构(树)1.1.1 二叉查找树1.1.2 二叉树的遍历 1.2 平衡二叉树树的演变 1.3 数据结构 ( 平衡二叉树 )左旋1.4 数据结构 ( 平衡二叉树 )右旋数据结构 (平衡二叉树)需要转的四种情况 1.5 红黑树添加节点规则 二、Set系列集…

基础算法(五):DFS、BFS与剪枝

前言 前面的基础算法笔记已经断更好久了,因为荔枝觉得还是得先学一下基础的数据结构知识之后才能更好的入门算法。在这篇文章中荔枝主要记录DFS和BFS的相关基础知识、答题的模板以及自己的一些浅薄理解,同样的也会涉及到相关的剪枝操作。 一、搜索算法概…