C++类和对象入门(三)

顾得泉:个人主页

个人专栏:《Linux操作系统》 《C++从入门到精通》  《LeedCode刷题》

键盘敲烂,年薪百万!


前言

       在c++中,类型分为两类,一类是内置类型,另一类是自定义类型。

1.内置类型:是指任何语言在设计初期定义的类型

        如:int long double 指针……

2.自定义类型:基本数据类型赋别名或基于一些基本数据类型定义新的复杂数据类型

        如:Stack Queue ……

       自定义类型函数会自动调用默认函数,而内置类型生成随机值(VS2013上取随机值,VS2019上生成1,这里我们默认生成随机值)。如果一个类中什么成员都没有,简称为空类。

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

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

一、构造函数

1.概念

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

对于以下date类:

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

       对于Date类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?

2.特性

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

       1.函数名与类名相同。

       2.无返回值。

       3.对象实例化时编译器自动调用对应的构造函数,不用在初始化。

       4.构造函数可以重载。

 class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1; // 调用无参构造函数Date d2(2015, 1, 1); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();}

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

class Date{public:/*// 如果用户显式定义了构造函数,编译器将不再生成Date(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类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函数// 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再生成// 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用Date d1;return 0;}

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

解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。

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;
}

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

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 = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}

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

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

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;
}

二、析构函数

1.概念

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

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

2.特性

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

       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;
};
void TestStack()
{Stack s;s.Push(1);s.Push(2);
}

       5.关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。

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

 结果如下:

 程序运行结束后输出:~Time()

       在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?

因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month, _day三个是 内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。

       但是,main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数。

注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数

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

结语:关于C++类和对象二次分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言,最后祝大家新的一年里学业有成,天天开心~~~ 

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

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

相关文章

Linux内存管理:(十二)Linux 5.0内核新增的反碎片优化

文章说明&#xff1a; Linux内核版本&#xff1a;5.0 架构&#xff1a;ARM64 参考资料及图片来源&#xff1a;《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址&#xff1a; zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 外碎片化发生时&#xff0c;页面分配…

Python基础知识:Python流程控制语句

流程控制就是控制程序如何执行的方法&#xff0c;适用于任何一门编程语言&#xff0c;其作用在于&#xff0c;可以根据用户的需求决定程序执行的顺序。计算机在运行程序时&#xff0c;有3种执行方法&#xff0c;第一种是顺序执行&#xff0c;自上而下顺序执行所有的语句&#x…

分享63个节日PPT,总有一款适合您

分享63个节日PPT&#xff0c;总有一款适合您 63个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1kZeiN06KbevtSCs5vXm6oA?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

【代码随想录-哈希表】两个数组的交集

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

MySQL 小技巧:使用 xtrabackup 2.4 实现 完全备份及还原

演示&#xff1a;使用 xtrabackup 2.4 实现 完全备份及还原 本案例基于 CentOS 7 的 Mariadb5.5 实现&#xff0c;也支持 MySQL5.5 和 MySQL5.7 1) 安装 xtrabackup 包 // 先安装 Mariadb5.5 和 xtrabackup 包 [rootcentos7 ~] yum install mariadb-server -y [rootcentos7 ~]…

AMH面板如何安装与公网远程访问本地面板界面

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

解析 JavaScript 异步编程:从回调地狱到 Promise 和 Async/Await

在现代的JavaScript开发中&#xff0c;处理异步任务变得愈发重要&#xff0c;因为它们允许我们在等待I/O、网络请求或定时器等事件时继续执行其他任务&#xff0c;以提高程序的性能和响应能力。本文将介绍JavaScript中异步编程的演变过程&#xff0c;从最初的回调地狱到后来的P…

容器和镜像

容器和镜像是现代软件开发和部署中重要的概念&#xff0c;它们通常与容器化技术&#xff08;如Docker&#xff09;相关联。以下是它们的基本定义和关系&#xff1a; 容器(Container): 容器是一种轻量级、可移植的运行环境&#xff0c;其中包含了应用程序及其依赖项&#xff08;…

简单实践 spring clound 使用openfeign

1.概要 这是在前面工程基础上的一个变更。 前工程&#xff1a;检查实验 spring cloud nacos nacos-server-2.3.0-CSDN博客 2 代码 2.1 引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-open…

您企业的(AI)人工智能处于哪个准备阶段?

全新AI准备度评估工具现已推出 根据Gartner 2020年CIO调查报告&#xff0c;仅19%的首席信息官声称其AI项目已投产。这意味着&#xff0c;如果要将AI计划部署到生产过程中&#xff0c;高达80%的企业无法实现。我们发现&#xff0c;澳鹏客户取得成功的几率要高出三倍&#xff0c…

C++类与对象(下)

前言&#xff1a;哈喽小伙伴们&#xff0c;这篇文章我们将继续分享类与对象的剩余知识。 目录 一.const修饰成员函数 二.再谈构造函数 三.友元 1.友元函数 2.友元类 总结 一.const修饰成员函数 我们都知道const是一个将变量定义为静态的关键字&#xff0c;使其不能被修改…

C语言之自定义类型:结构体

目录 1. 结构体类型的声明结构体回顾结构的声明 2. 结构体变量的创建和初始化结构体的特殊声明结构体的自引用 3. 结构体内存对齐对齐规则对齐规则练习1对齐规则练习2对齐规则练习3对齐规则练习4 为什么存在内存对齐offsetof - 计算结构体成员相较于起始位置的偏移量修改默认对…

协同办公的2024开年大战,打的就是“超级助理”

文|智能相对论 作者|沈浪 开年&#xff0c;腾讯发布了一份报告《影响2024年的十大科技应用趋势》。其中提到&#xff0c;从大脑到Agent&#xff0c;大模型从CoPilot副驾&#xff0c;走向主驾驶。在不久的将来&#xff0c;任何上网的人都将能够拥有由人工智能驱动的个人助手&a…

Java学习-内部类

内部类概述 1.成员内部类 注意&#xff1a; 2.静态内部类 3.局部内部类&#xff08;看看就行&#xff09; 4.匿名内部类 应用场景&#xff1a;通常作为一个参数传给方法 Eg.小猫和小狗都参加游泳比赛

【算法】{画决策树 + dfs + 递归 + 回溯 + 剪枝} 解决排列、子集问题(C++)

文章目录 1. 前言2. 算法例题 理解思路、代码46.全排列78.子集 3. 算法题练习1863.找出所有子集的异或总和再求和47.全排列II17.电话号码的字母组合 1. 前言 dfs问题 我们已经学过&#xff0c;对于排列、子集类的问题&#xff0c;一般可以想到暴力枚举&#xff0c;但此类问题用…

单片机的50个电路

单片机 电源 声音模块 收音机 485 蓝牙 光耦 can 光敏电阻 单片机 矩阵 单片机电路 时钟 ADC 接口电路 红外发射 显示模块 红外接收 蜂鸣器驱动 流水灯 usb供电 烧录电路 数码管 EEPROM LCD1602电路 数码管 max485 红外开关 译码器 移位寄存器 步进电机控制 复位电路 下载电路 …

基于springboot智慧养老平台源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

挑战!贪吃蛇小游戏的实现(1)

引言 相信大家都玩过贪吃蛇这个游戏&#xff01; 玩家控制一个不断移动的蛇形角色&#xff0c;在一个封闭空间内移动。随着时间推进&#xff0c;这个蛇形角色会逐渐增长&#xff0c;通常是通过吞食屏幕上出现的物品&#xff08;如点或者其他标志&#xff09;来实现。每当贪吃…

《低功耗方法学》翻译——附录B:UPF命令语法

附录B&#xff1a;UPF命令语法 本章介绍了文本中引用的所选UPF命令的语法。 节选自“统一电源格式&#xff08;UPF&#xff09;标准&#xff0c;1.0版”&#xff0c;经该Accellera许可复制。版权所有&#xff1a;(c)2006-2007。Accellera不声明或代表摘录材料的准确性或内容&…

monaco-editor布局篇(二)-自动换行

monaco-editor的换行方式&#xff0c;主要分为3种情况&#xff1a; 不换行按照编辑器宽度换行按照制定列数换行 主要受wordwrap和wordwrapcolumn控制&#xff0c;具体如下&#xff1a; 取值含义off不换行&#xff0c;会一直滚动on换行&#xff0c;文本将在视区宽度内自动换行…