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

欢迎来到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.hqwc.cn/news/650727.html

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

相关文章

GaN HEMT中短沟道效应的建模

来源&#xff1a;Modeling of Short-Channel Effects in GaN HEMTs&#xff08;TED 20年&#xff09; 摘要 在本文中&#xff0c;我们提出了一种用于估算GaN高电子迁移率晶体管&#xff08;HEMT&#xff09;器件中短沟道效应&#xff08;SCEs&#xff09;的显式和解析的基于电…

手搓单链表(无哨兵位)(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;//打印…

vue2项目升级到vue3经历分享1

依据vue官方文档&#xff0c;vue2在2023年12月31日终止维护。因此决定将原来的岁月云记账升级到vue3&#xff0c;预计工作量有点大&#xff0c;于是想着把过程记录下来。 原系统使用的技术栈 "dependencies": {"axios": "^0.21.1","babel-…

springboot+vue新疆肉牛智慧牧场养殖系统

系统涉及的对象是奶牛。 系统使用员工有管理员和普通员工。 管理员有修改的权限&#xff0c;普通员工没有。 系统需要包含奶牛的编号&#xff0c;种类&#xff0c;体重&#xff0c;健康情况、生长情况、牛奶产量&#xff0c;以及上次更新数据时间等信息&#xff0c;管理员可以对…

回归预测 | Matlab实现SSA-ESN基于麻雀搜索算法优化回声状态网络的多输入单输出回归预测

回归预测 | Matlab实现SSA-ESN基于麻雀搜索算法优化回声状态网络的多输入单输出回归预测 目录 回归预测 | Matlab实现SSA-ESN基于麻雀搜索算法优化回声状态网络的多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现SSA-ESN基于麻雀搜索算法…

深圳证券交易所Binary行情数据接口规范

对接深圳证券交易所Binary行情数据接口其实并不难&#xff0c;你需要具备以下知识。 1、需要了解Binary报文设计结构&#xff0c;消息头消息体消息尾。 消息体&#xff1a; 如果是纯map结构的比较简单&#xff0c;字段平铺开来即可。如{"id":"1","…

JEECG/SpringBoot集成flowable流程框架

IDEA安装Flowable BPMN visualizer插件 pom.xml中引入flowable相关依赖 <dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>6.7.2</version></dependency><depe…

盘点数据资产管理十大活动职能 优化企业数据资产管理和应用

在当今的数字化时代&#xff0c;数据已成为企业最宝贵的资产之一&#xff0c;在上篇文章中我们对数据资产管理进行了初步的介绍。 上篇文章指路&#x1f449;什么是数据资产管理&#xff1f;详谈数据资产管理的难点与发展现状&#xff01; 有效的数据资产管理不仅能提升企业的…

JavaScript-2(运算符+流程控制+数组+函数+作用域)

目录 1.运算符 比较运算符 浮点数的精度问题 递增或递减运算符 前置递增运算符 后置递增运算符 比较运算符 逻辑运算符 短路运算&#xff08;逻辑中断&#xff09; 赋值运算符 运算符优先级 2.流程控制 顺序结构 分支结构 if语句 switch语句 二者区别 三元表…

IOTE2024第二十一届(上海)国际物联网展览会4月24日-26日开幕

交流产业信息&#xff0c;把脉发展方向&#xff0c;IOTE 国际物联网展是每年物联网行业、企业、用户交流合作的大型平台。2024年4月24-26日IOTE2024第二十一届国际物联网展•上海站&#xff0c;在上海世博展览馆开展。 本次物联网展汇聚全球超300家参展企业、3万来自工业、物流…

【讯为Linux驱动笔记1】申请一个字符设备

Linux下每个设备都需要有一个专属设备号&#xff1a;主设备号 次设备号 【申请字符设备】 主设备号&#xff1a;一类驱动&#xff1a;如&#xff1a;USB驱动 次设备号&#xff1a;这类驱动下的某个设备 如&#xff1a;键盘鼠标 设备号是32位的dev_t类型的&#xff0c;高12位主…

酒店大厅装智能酒精壁炉前和装后对比

安装智能酒精壁炉前后&#xff0c;酒店大厅的氛围和效果会有显著的对比&#xff1a; 装前&#xff1a; 普通装饰&#xff1a; 大厅可能显得比较普通&#xff0c;缺乏独特的装饰和氛围元素。 空间感较弱&#xff1a; 大厅可能缺乏焦点和吸引力&#xff0c;客人进入后感觉空间…