【C++】C++中的构造函数和析构函数详解

news2024/11/25 23:01:25

欢迎来到CILMY23的博客

本篇主题为:C++中的构造函数和析构函数详解

个人主页:CILMY23-CSDN博客

系列专栏:Python | C++ | C语言 | 数据结构与算法

感谢观看,支持的可以给个一键三连,点赞关注+收藏。


 写在前头:

本篇会从类的六个默认成员函数开始,进入构造函数和析构函数的了解。


目录

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

二、构造函数

2.1 构造函数的概念

2.2 构造函数的特点

无参和有参的构造函数 

2.3 随机值的初始化 

三、析构函数

 3.1 析构函数概念

3.2 析构函数的特点 


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

在上篇文章中(点击链接跳转),我们涉及到一个特殊类,这个类中什么成员都没有,其大小为1字节,我们将如果一个类中什么成员都没有,简称为空类

 例如:A1不是空类,A2是空类。

class A1
{
public:
	void f1(){}
};
 
class A2{};

空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员 函数。

什么是默认成员函数?
默认成员函数指的是用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数

 9f17fce17cac4584841ce84e604964f2.png

二、构造函数

构造函数作为类默认成员函数中特殊的成员函数,是面向对象编程中非常重要的概念,那什么是构造函数呢?

2.1 构造函数的概念

现在我们有一个简易的学生类,注意,参数类型是const char*,而不是char(因为传入的参数是常量字符串,类型为const char*)

#include<iostream>
using namespace std;

class Student
{
public:
	void Init(const char* name,int age,const char* ID)
	{
		strcpy(_name, name);
		_age = age;
		strcpy(_ID, ID);
	}
	void Print()
	{
		cout <<"学生姓名:" << _name << endl;
		cout <<"学生年龄:" << _age << endl;
		cout <<"学生学号:" << _ID << endl;
	}
private:
	char _name[20];
	int _age;
	char _ID[20];
};

int main()
{
	Student stu1;
	stu1.Init("zhangsan", 21, "20001216A11");
	
	stu1.Print();
	return 0;
}

那我们每次初始化都要调用一个Init,或者经常忘记初始化,能否省略这个步骤呢?于是C++里就引入了构造函数这个概念。

构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用,以保证 每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次。 

2.2 构造函数的特点

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

 构造函数的特点如下:

  1. 函数名与类名相同。
  2. 无返回值。(无返回值不是void,而是不需要写)
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载

构造函数也分无参有参数类型 

无参和有参的构造函数 

例如:

class Student
{
public:
	//无参构造函数
	Student()
	{
		strcpy(_name, "xxxxxx");
		_age = 0;
		strcpy(_ID, "xxxxxxx");
	}
	//有参构造函数
	Student(const char*name,int age,const char* ID)
	{
		strcpy(_name, name);
		_age = age;
		strcpy(_ID, ID);
	}
	void Print()
	{
		cout << "学生姓名:" << _name << endl;
		cout << "学生年龄:" << _age << endl;
		cout << "学生学号:" << _ID << endl;
	}
private:
	char _name[20];
	int _age;
	char _ID[20];
};

int main()
{
	Student stu1;//调用了无参的构造函数
	stu1.Print();

	Student stu2("zhangsan", 21, "20001216A11");//调用有参的构造函数
	stu2.Print();
	return 0;
}

 在学生类中,两个构造函数构成函数重载。在对象实例化的时候,自动调用了对应构造函数,在这个学生类,我们使用了构造函数来初始化对象,但是注意在调用无参函数的时候不加 ()。

2.3 随机值的初始化 

 我们说构造函数,是默认的成员函数,编译器一定会调用,但是它并没有初始化?

我们看个例子: 

class Student
{
public:
	void Print()
	{
		cout << "学生姓名:" << _name << endl;
		cout << "学生年龄:" << _age << endl;
		cout << "学生学号:" << _ID << endl;
	}
private:
	char _name[20];
	int _age;
	char _ID[20];
};

int main()
{
	Student stu1;//调用默认的构造函数
	stu1.Print();

	return 0;
}

结果:

0dda18fd4e634997a91feab8baea281f.png它不是会初始化吗?但是为什么这里没有初始化,按道理来说,应该是根据类型不同,我们就直接赋值,比如,整型给0,浮点数给0.0……

其实C++把类型分成内置类型(基本类型)自定义类型内置类型就是语言提供的数据类型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型默认生成的构造函数,对于内置类型不做处理,自定义类型会去调用它的默认构造函数

例如:

class P
{
public:
	P()
	{
		cout << "P()" << endl;
		_P = 0;
	}
private:
	int _P;
};

class Student
{
public:
	void Print()
	{
		cout << "学生姓名:" << _name << endl;
		cout << "学生年龄:" << _age << endl;
		cout << "学生学号:" << _ID << endl;
	}
private:
	char _name[20];
	int _age;
	char _ID[20];

	P p1; //对自定义类型调用对应的默认构造函数
};

int main()
{
	Student stu1;//调用默认的构造函数
	stu1.Print();

	return 0;
}

C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。 

 例如:

class Student
{
public:
	void Print()
	{
		cout << "学生姓名:" << _name << endl;
		cout << "学生年龄:" << _age << endl;
		cout << "学生学号:" << _ID << endl;
	}
private:
	char _name[20] = "xxxx"; //注意这里还是声明,声明给缺省值
	int _age = 0;
	char _ID[20]= "xxxxxxxx";
};

int main()
{
	Student stu1;//调用默认构造函数
	stu1.Print();

	return 0;
}

三、析构函数

通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的? 

 3.1 析构函数概念

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

3.2 析构函数的特点 

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

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

 学生类的析构函数:

class Student
{
public:
	void Print()
	{
		cout << "学生姓名:" << _name << endl;
		cout << "学生年龄:" << _age << endl;
		cout << "学生学号:" << _ID << endl;
	}
	~Student()//析构函数
	{
		cout << "~Student()" <<endl ;
	}
private:
	char _name[20]; 
	int _age;
	char _ID[20];
};

int main()
{
	Student stu1;//调用默认构造函数
	stu1.Print();

	return 0;
}

如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date,我们简易的学生类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类 。


总结:

  •  构造和析构类似初始化和销毁
  •  构造函数的主要任务并不是开空间创建对象,而是初始化对象。 
  •  调用无参函数的时候不加 ()
  •  对象实例化的时候,一定调用构造函数,否则报错
  • 全缺省构造函数和无参可能会在调用的时候出问题,并不是不可以同时存在(构成函数重载),而是调用出现歧义
  • 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
  • 无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。(一般情况写全缺省)
  • C++11 中内置类型成员变量在类中声明时可以给默认值。 
  • 默认生成的析构函数,对于内置类型不做处理,自定义类型会去调用它的默认析构函数

感谢各位同伴的支持,本期析构函数和构造函数篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

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

相关文章

【算法一则】【动态规划】求二维数组可组成的最大正方形

题目 在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内&#xff0c;找到只包含 ‘1’ 的最大正方形&#xff0c;并返回其面积。 示例 1&#xff1a; 输入&#xff1a;matrix [["1","0","1","0","0"],["1","0&…

为何鸿蒙开发成为求职市场的香饽饽 ?

在当今社会&#xff0c;技术的快速发展与更新迭代使得职场竞争愈发激烈。对于求职者来说&#xff0c;掌握一门热门且前景广阔的技术&#xff0c;无疑是获得理想工作的关键。鸿蒙开发&#xff0c;作为华为自主研发的操作系统开发技术&#xff0c;正逐渐成为求职市场的热门选择。…

手搓单链表(无哨兵位)(C语言)

目录 SLT.h SLT.c SLTtest.c 测试示例 单链表优劣分析 SLT.h #pragma once#include <stdio.h> #include <assert.h> #include <stdlib.h>typedef int SLTDataType;typedef struct SListNode {SLTDataType data;struct SListNode* next; }SLTNode;//打印…

触发器的基本概念及分类

目录 触发器的基本概念 作用对象 触发事件 触发条件 触发时间 触发级别或者触发频率 触发器的分类 DML 触发器 INSTEAD OF 触发器 系统触发器 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 触发器的基本概念 …

表格的单元格合并和表头的合并——vxe-table

vxe-table的官网&#xff1a;https://vxetable.cn/#/table/advanced/mergeCell在你的项目中下载安装完成后&#xff0c;先在main.js文件中引入&#xff1a; import VXETable from vxe-table import vxe-table/lib/style.css Vue.use(VXETable)一、单元格合并 效果图&#xff…

2024年【安全生产监管人员】考试技巧及安全生产监管人员模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【安全生产监管人员】考试技巧及安全生产监管人员模拟考试&#xff0c;包含安全生产监管人员考试技巧答案和解析及安全生产监管人员模拟考试练习。安全生产模拟考试一点通结合国家安全生产监管人员考试最新大纲…

Java | Leetcode Java题解之第50题Pow(x,n)

题目&#xff1a; 题解&#xff1a; class Solution {public double myPow(double x, int n) {long N n;return N > 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);}public double quickMul(double x, long N) {if (N 0) {return 1.0;}double y quickMul(x, N / 2);retu…

大数据开发详解

点击下载《大数据开发详解》 1. 前言 随着信息化时代的快速发展&#xff0c;大数据已经成为了企业和组织不可或缺的重要资源。大数据开发则是指通过一系列技术手段&#xff0c;对海量数据进行收集、存储、处理、分析和挖掘&#xff0c;以实现数据的价值化利用。大数据开发涉及…

进口透明可视耐腐蚀PFA进样管特氟龙圆底试管适配MC-ICP-MS

PFA进样管可适配Neptune plus多接收器等离子质谱仪&#xff08;MC-ICP-MS&#xff09;&#xff0c;广泛应用于地球化学、核保障、环境科学、金属组学领域&#xff0c;在生物、物理、化学、材料等多个学科的交叉方向也有良好的应用前景。 外观半透明&#xff0c;便于观察管内情…

YOLOV5 TensorRT部署 BatchedNMS(engine模型推理)(下)

主要是在王新宇代码的基础上改进,引入对BatchedNMS的解码 文章目录 1. 修改yolov5.cpp2.修改yololayer.h1. 修改yolov5.cpp 首先增加全局变量,名字根据转onnx时修改的节点名字来,查看onnx文件可以看到,顺序不要弄错。 const char *INPUT_NAME = “images”; const char …

基于深度学习的实时人脸检测与情绪分类

情绪分类 实时人脸检测与情绪分类 Kaggle Competion 数据集 fer2013 中的测试准确率为 66%CK数据集的检验准确率为99.87%情绪分类器模型预测从网络摄像头捕获的实时视频中的平均成本时间为 4~ 10ms 关键技术要点&#xff1a; 实时人脸检测&#xff1a;系统采用了前沿的人脸检…

提交链码-编辑前后端,调用链码功能

一 . 链码介绍 1.什么链码&#xff1f; • 链码是一段用 Go、Node.js 或者 Java 实现了规定接口的程序。链码在安全的Docker容器中运行&#xff0c; 与背书节点的进程隔离。通过应用程序提交的交易&#xff0c;链码初始化和管理账本状态。• 链码通常处理网络成员协商达成的业…

vue下载文件时显示进度条

1.单个下载&#xff08;开始是导出按钮 下载显示进度条&#xff09; html <el-button click.stop"exportReport(scope.row, scope.index)" v-if"!scope.row.schedule" icon"el-icon-download"size"small" type"text"styl…

2023最新!MySQL8于win10环境下的安装配置保姆级教程

2023最新&#xff01;MySQL8于win10环境下的安装配置保姆级教程 MySQL官网&#xff1a;https://www.mysql.com/downloads/ 导航 文章目录 2023最新&#xff01;MySQL8于win10环境下的安装配置保姆级教程导航一、MySQL下载二、安装MySQLchoosing a Setup Typeselect products…

软件测试面试题(三)

Selenium 相关Selenium 基础什么是 Selenium&#xff1f;什么是 Selenium WebdriverS 什么是 elenium IDE&#xff1f;常用自动化测试工具机器运行原理&#xff0c;写出一段元素查找的代码&#xff1f;如何开展自动化测试框架的构建&#xff1f;如何设计自动化测试用例webdrive…

Angular 由一个bug说起之五:为什么现代CSS系统倾向于少用或不用absolute定位?

在现代网页设计中&#xff0c;CSS&#xff08;层叠样式表&#xff09;是不可或缺的一部分。在过去&#xff0c;使用position: absolute定位元素是一种常见的技术&#xff0c;但是随着前端开发的发展&#xff0c;现代CSS系统倾向于减少或避免使用absolute定位。本文将探讨这一趋…

上班族必备的便签备忘录app 好用的便签备忘录软件

上班族每天都需要处理大量的工作事项&#xff0c;从策划方案到客户沟通&#xff0c;每一个环节都至关重要。然而&#xff0c;仅仅依靠大脑记忆&#xff0c;很容易遗漏某些细节&#xff0c;甚至可能错过重要的截止日期。为了避免这种情况&#xff0c;许多人选择使用一款优秀的便…

NATAPP内网穿透工具安装和使用教程

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 必须要按照先操作完第一步 再操作第二步骤下载教程 1.进入网址注册&#xff1a;NATAPP - 2.下载网址&#xff1a;NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 流程 注册NATAPP 实名认证通过之后…

学习笔记Label自右向左滚动和父容器内左右移动方法(含代码)

一、【滚动效果】 【radialMenu1控件】菜单切换浏览器和控制台 需要定时器Timer&#xff08;默认属性EnabledFalse,Interval100&#xff09; 二、【方法1和方法2&#xff0c;通过属性切换开关和方向】 try{if (myObject.TextScrollSwitch){//打开移动if(myObject.TextScroll…

固态继电器:推进可再生能源系统

随着可再生能源系统的发展&#xff0c;太阳能系统日益成为现代能源解决方案的先锋。在这种背景下&#xff0c;固态继电器&#xff08;SSR&#xff09;&#xff0c;特别是光耦固态继电器的利用变得日益突出。本文旨在深入探讨SSR在可再生能源系统中的多方位应用&#xff0c;重点…