【C++入门】构造函数析构函数

 

目录

 前言

 1. 类的默认成员函数

 2. 构造函数

  2.1 什么是构造函数

2.2 构造函数的特性

3. 析构函数

 3.1 什么是析构函数

 3.2 析构函数的特性


 前言

        前边我们已经了解了类和对像的基本概念,今天我们将继续深入了解类。类有6个默认成员函数,即使类中什么都不写(空类),编译器会自动生成6个默认成员函数。那么本期主要介绍的是构造函数和析构函数。

在这里插入图片描述

 1. 类的默认成员函数

         默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

即使是类中什么都不写,编译器也会自动生成以下6个默认成员函数:

 既然会默认生成那还有什么必要介绍呢?

       虽然编译器会默认生成,但也并不是适用于任何场景(一些自定义类型不适用),这时就需要我们自己实现,所以深入了解类内部默认成员函数非常有必要的。

 2. 构造函数

  2.1 什么是构造函数

我们先看下面这个例子:

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(2023, 11, 10);d1.Print();Date d2;d2.Init(2022, 11, 10);d2.Print();return 0;
}

 这种写法其实很不便捷,比如:

  • 每次创建对象需要手动调用
  • 可能出现忘记调用的情况

 为了使用便捷于是C++引入了新的玩法:

 构造函数(用于初始化)

2.2 构造函数的特性

 注意:

 构造函数的主要任务并不是开空间创建对象,而是初始化对象。

 构造函数有以下特性:

  • 函数名与类名相同
  • 无返回值
  • 创建对象时编译器自动调用对应的构造函数
  • 在对象生命周期中只调用一次
  • 构造函数可以重载 
class Data
{
public:Data(){_year = 6;_month = 6;_day = 6;}Data(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()
{Data d1;// 调用无参构造函数//通过无参构造函数创建对象时,对象后面不用跟括号,会被识别成函数调用Data d2(2023, 10, 20);// 调用带参的构造函数return 0;
}
  • 用户显式定义了构造函数,编译器将不再生成
class Date
{
public://显式定义了构造函数,编译器不再生成Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
int main()
{	Date d1;//报错,没有合适的默认构造函数可用//创建对象时没有参数,应该调用无参构造,并且上述构造没有缺省值//编译器默认生成的构造初始化为随机值return 0;
}

我们再来看看自定义类型:

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;//创建Date对象d,没有写构造函数也会生成默认构造return 0;
}

默认生成的构造函数初始化分为两种:

  • 内置类型
  • 自定义类型

内置类型:编译器默认的构造函数会初始化为随机值(也可能是0,不同编译器之间有差别)

自定义类型:会调用它的默认构造

比如:

 _t会调用Time类里边的默认构造

 C++中将内置类型初始化为随机值是一个缺陷

 C++11 针对这个缺陷,打了补丁:

  • 内置类型成员变量在类中声明时可以给默认值

 默认构造函数有三种

  1. 无参的构造函数
  2. 全缺省的构造函数
  3. 我们没写编译器默认生成的构造函数

 注意:默认构造函数只能有一个

 比如:

class Date
{
public:Date(){_year = 1900;_month = 1;_day = 1;}Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};void Test()
{Date d1;//报错,无法通过编译//d1是无参对象,调用构造函数时编译器分不清要调用哪个
}

3. 析构函数

 3.1 什么是析构函数

 前边我们以经知道一个对象是怎么来的

 那一个对象又是怎么没的呢?

 析构函数:

完成对象中资源的清理工作

 它的功能与构造函数相反

对象在销毁时会自动调用析构函数,完成对象中资源的清理工作 

注意:

  • 析构函数不是完成对对象本身的销毁
  • 局部对象销毁工作是由编译器完成的

 3.2 析构函数的特性

   析构函数有以下特性:

  • 析构函数名是在类名前加上字符 ~。
  • 无参数无返回值类型。
  • 一个类只能有一个析构函数。
  • 若未显式定义,系统会自动生成默认的析构函数。
  • 析构函数不能重载
  • 对象生命周期结束时,自动调用析构函数(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;
};
void TestStack()
{Stack s;s.Push(1);s.Push(2);
}

 在栈使用结束后不需要手动调用

出了作用域自动销毁

它的行为和构造函数很相似:

  •  默认生成析构函数,行为跟构造类似
  •  内置类型成员不做处理
  •  自定义类型成员会去调用他的析构

 比如:

class MyQueue
{private://MyQueue生成默认构造要清理_pushst和_popst两个成员变量时//就会调用Stack类里的析构函数Stack _pushst;Stack _popst;int _size = 1;
};int main()
{//main函数结束清理对象//MyQueue类会自动生成默认析构函数行为如下://内置类型不做处理//自定义类型调用它的析构函数MyQueue mq;return 0;
}

 总结:

         如果类中没有申请资源时(动态内存管理),析构函数可以不写,直接使用编译器生成的默认析构函数,有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

       好了以上便是本期的全部内容,构造函数和析构函数的理解非常重要,关键也就总结为一句话:创建哪个类的对象就调用哪个类的构造函数,销毁哪个类的对象就调用哪个类的析构函数。希望对你有所帮助,感谢阅读!

 

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

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

相关文章

C#开发的OpenRA游戏之世界存在的属性CombatDebugOverlay(3)

C#开发的OpenRA游戏之世界存在的属性CombatDebugOverlay(3) 这次来分析CombatDebugOverlay属性,这个属性只有在调试游戏的时候才会使用。当你设置这个属性的时候,就可以看到如下图的结果: 可以看到物品的周边都有一个圆圈,以及有一些十字的点位标志。 那些十字表示的点…

Python实现局部二进制算法(LBP)

1.介绍 局部二进制算法是一种用于获取图像纹理的算法。这算法可以应用于人脸识别、纹理分类、工业检测、遥感图像分析、动态纹理识别等领域。 2.示例 """ 局部二进制算法&#xff0c;计算图像纹理特征 """ import cv2 import numpy as np imp…

小程序游戏对接广告收益微信小游戏抖音游戏软件

小程序游戏对接广告是一种常见的游戏开发模式&#xff0c;开发者可以通过在游戏中嵌入广告来获取收益。以下是一些与小程序游戏对接广告收益相关的关键信息&#xff1a; 小程序游戏广告平台选择&#xff1a; 选择适合你的小程序游戏的广告平台非常重要。不同的平台提供不同类型…

iview实现table里面每行数据的跳转

我的需求是跳转到第三方网站&#xff0c;看官方是写了如何跳转站内路由&#xff0c;不符合我的要求&#xff0c;在csdn发现了一篇文章&#xff0c;我贴一下代码 <template><Table border :columns"ReportColumns" :data"ReportData"><templ…

odoo16 库存初始化 excel导入问题

最近在为一家公司实施odoo时&#xff0c;发现库存模块实施过程中按用户实际&#xff0c;产品初始化就是个问题。下面一一记录下 一个新公司&#xff0c;产品都有上百种&#xff0c;甚致几千种&#xff0c;如何把现有产品数据录入系统就是个不小的活。odoo16是有导入导出功能不…

悟空crm二次开发 增加客户保护功能 (很久没有消息,但是有觉得有机会的客户)就进入了保护转态

需求&#xff1a;客户信息录入不限数量&#xff0c;但是录入的信息1个月内只有自己和部门领导能看到&#xff0c;如果1个月内未成交或者未转移至自己的客保 则掉入公海所有人可见&#xff0c;这里所说的客保就是现在系统自带的客保 1、需求思维导图 2、新增保护按钮 3、点击该…

C++初阶--类与对象(3)(图解)

文章目录 再谈构造函数初始化列表隐式类型转换explicit关键字 static成员友元类内部类匿名对象拷贝函数时的一些优化 再谈构造函数 在我们之前的构造函数中&#xff0c;编译器会通过构造函数&#xff0c;对对象中各个成员给出一个适合的初始值&#xff0c;但这并不能称之为初始…

QT 布局管理综合实例

通过一个实例基本布局管理&#xff0c;演示QHBoxLayout类、QVBoxLayout类及QGridLayout类效果 本实例共用到四个布局管理器&#xff0c;分别是 LeftLayout、RightLayout、BottomLayout和MainLayout。 在源文件“dialog.cpp”具体代码如下&#xff1a; 运行效果&#xff1a; Se…

Redis的内存淘汰策略分析

概念 LRU 是按访问时间排序&#xff0c;发生淘汰的时候&#xff0c;把访问时间最久的淘汰掉。LFU 是按频次排序&#xff0c;一个数据被访问过&#xff0c;把它的频次 1&#xff0c;发生淘汰的时候&#xff0c;把频次低的淘汰掉。 几种LRU策略 以下集中LRU测率网上有很多&am…

浙江大学漏洞报送证书

获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;主页 | 教育漏洞报告平台 兑换价格&#xff1a;20金币 获取条件&#xff1a;提交浙江大学任意中危或以上级别漏洞

selenium xpath定位

selenium-xpath定位 <span style"background-color:#2d2d2d"><span style"color:#cccccc"><code class"language-javascript">element_xpath <span style"color:#67cdcc"></span> driver<span styl…

在gitlab中指定自定义 CI/CD 配置文件

文章目录 1. 介绍2. 配置操作3. 配置场景3.1 CI/CD 配置文件在当前项目step1&#xff1a;在当前项目中创建目录&#xff0c;编写流水线文件存放在该目录中step2&#xff1a;在当前项目中配置step3&#xff1a;运行流水线测试 3.2 CI/CD 配置文件位于外部站点上step1&#xff1a…

掌动智能性能压力测试优势有哪些

企业通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。本文将介绍性能压力测试的价值及主要优势! 一、性能压力测试的价值 1、评估系统能力&#xff1a;有助于参数的基准测试&#xff0c;可以度量系统的响应时间;还有助于检查系统是否可…

OpenCV-Python小应用(九):通过灰度直方图检测图像异常点

OpenCV-Python小应用&#xff08;九&#xff09;&#xff1a;通过灰度直方图检测图像异常点 前言前提条件相关介绍实验环境通过灰度直方图检测图像异常点代码实现输出结果 参考 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#xff…

基于springboot实现高校党务平台管理系统【项目源码】

基于springboot实现高校党务平台管理系统演示 Java技术 Java是由Sun公司推出的一门跨平台的面向对象的程序设计语言。因为Java 技术具有卓越的通用性、高效性、健壮的安全性和平台移植性的特点&#xff0c;而且Java是开源的&#xff0c;拥有全世界最大的开发者专业社群&#x…

ubuntu16.04 交叉编译 mbedtls

在为客户交叉编译项目时需要依赖 mbedtls&#xff0c; 客户的机器是 arm64 的 ubuntu 16.04&#xff0c; 交叉编译过程中遇到几个问题。 首先&#xff0c; mbedtls 需要依赖 python, 在 cmake 的过程中&#xff0c; 如果不是使用系统默认的 cmake 可能会导致&#xff0c;mbedt…

蓝桥杯算法双周赛心得——被替换的身份证(分类讨论)

大家好&#xff0c;我是晴天学长&#xff0c;分类讨论一定要细节啊&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .被替换的身份证 2) .算法思路 假设一方获胜 1.接受数据 2.假设潜梦醒 无非就是&am…

计算机组成原理之处理器(单周期)

引言 处理器的实现方式决定了时钟周期长度和CPI。实现方式有单周期与流水线&#xff0c;本篇谈谈单周期处理器。 目前CPU的频率一般是3GHZ/4GHZ&#xff0c;但是频率是有极限值的&#xff0c;受cycletime影响 基本的RISC-V实现 存储指令&#xff1a;ld,sd算术逻辑指令 &…

AI 绘画 | Stable Diffusion 进阶 Embeddings(词嵌入)、LoRa(低秩适应模型)、Hypernetwork(超网络)

前言 Stable Diffusion web ui&#xff0c;除了依靠文生图&#xff08;即靠提示词生成图片&#xff09;&#xff0c;图生图&#xff08;即靠图片提示词生成图片&#xff09;外&#xff0c;这两种方式还不能满足我们所有的绘图需求&#xff0c;于是就有了 Embeddings&#xff0…

京东数据分析:2023年Q3户外鞋服市场分析报告(冲锋衣行业销售数据分析)

从露营、骑行、徒步、桨板、垂钓、飞盘、滑雪到如今的city walk&#xff0c;近两年户外运动已经成为了年轻人新的生活方式。户外运动的爆发也刺激了人们对于鞋服在穿搭、场景化、专业性功能等方向的需求&#xff0c;户外鞋服市场迎来增长。 而全国性的降温则带给目前的户外鞋服…