C++ 类和对象篇(三) 空类和6个默认成员函数

目录

一、空类

1. 是什么?

2. 空类中的成员

3. 空类的大小

二、6个默认成员函数

三、 构造函数

1. 构造函数是什么?

2. 为什么C++要引入构造函数?

四、析构函数

1. 析构函数是什么?

2. 为什么要有析构函数?

五、拷贝构造函数

1. 拷贝构造函数是什么?

2. 为什么要有拷贝构造函数?

六、赋值运算符重载函数

1. 运算符重载是什么?

2. 为什么要运算符重载?

3. 默认赋值运算符重载函数

七、取地址运算符重载

1. 为什么需要重载取地址运算符?

2. 默认取地址运算符重载函数

3. 默认const取地址运算符重载函数

八、默认成员函数什么情况需要显示去写?


一、空类

1. 是什么?

如果一个类中没有显示定义任何成员,简称为空类。

class A {};//一个空类

2. 空类中的成员

空类中真的什么都没有吗?

并不是,任何类都有6个不在类中实现,编译器会自动生成的默认成员函数。

3. 空类的大小

        注意,没有成员变量的类(包括空类)的大小为1字节,不存储数据,目的是为了占位,标识对象存在,区分不同的对象。所以,空类同样可以被实例化,并且每个实例在内存中都有独一无二的地址。


二、6个默认成员函数

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

1)构造函数:在创建对象时初始化对象中的成员变量。

2)析构函数:完成对象的销毁。

3)拷贝构造函数:有了该函数能用同类对象初始化创建对象。

4)赋值重载函数:有了该函数能把一个对象赋值给另一个对象。

5)普通对象取地址重载函数:主要是对普通对象取地址,这个很少会自己实现。

6)const对象取地址重载函数:主要是对const对象取地址,这个很少会自己实现。

不能以普通函数的定义和调用规则去理解以上6个函数。


三、 构造函数

1. 构造函数是什么?

        构造函数是一个特殊的成员函数用来初始化成员变量,函数名和类名相同,使用实例化对象时由编译器自动调用,并且在对象整个生命周期内只调用一次。

2. 为什么C++要引入构造函数?

        怎么对类中的成员变量进行初始化?写一个成员函数专门用来初始化成员变量?但如果忘记调用了怎么办?为解决类初始化和忘记初始化类的问题,能不能在创建对象时就自动完成初始化的动作呢?

举个小例子: 
有以下Date类:
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};如果要使用该Date类创建对象,必须通过Init公有方法给对象设置日期,否则成员变量都是随机值,
但每次创建对象时都调用该方法,这未免有点麻烦,那能否在对象创建的同时,就将信息设置进去呢?

        为解决以上问题,C++中引入了构造函数:构造函数用于对象的初始化,在实例化对象时由编译器自动调用,保证了对象创建出来一定完成了初始化。虽然构造函数叫做构造,但构造函数并不用来开空间创建对象,而是用来初始化对象的。(也许构造函数更适合被称为初始化函数?) 

想要更深入的了解析构函数,可以看看博主的文章: C++ 类和对象篇(四) 构造函数


四、析构函数

1. 析构函数是什么?

        析构函数是一个特殊的成员函数,用来释放对象使用的资源(如关闭文件、释放内存等)。

2. 为什么要有析构函数?

        如何释放对象申请的系统资源?忘记释放怎么办?能不能在销毁对象时自动释放?

举个小例子:
class Test
{
public://构造函数Test(){_arr = (char*)malloc(1024*1024*1024);//申请1G空间}//销毁函数:用于释放资源void Destory(){free(_arr);}
private:char* _arr;
};int main()
{Test* t = new Test;//在堆上创建一个对象delete t;//销毁一个对象while (1) {}return 0;
}如果要销毁Test对象,必须先使用Destory公有方法来释放资源,否则会造成内存泄漏,
这未免有点麻烦,而且容易忘记,那能否在对象销毁的同时释放资源呢?

将以上程序运行起来,对比前后的内存变化,可以发现销毁对象前如果忘记释放资源,就会造成内存泄漏等问题。

程序运行前: 

程序运行后:


        所以为避免C++使用者在销毁对象时忘记释放对象使用的资源的问题,C++引入了析构函数,在析构函数里写释放资源的代码,在对象销毁时编译器会自动调用析构函数释放对象使用的资源。

        析构函数相对于自己写的销毁函数,其优势在于不需要自己去显示调用。 

想要更深入的了解构造函数,可以看看博主的文章:C++ 类和对象篇(五) 析构函数


五、拷贝构造函数

1. 拷贝构造函数是什么?

        拷贝构造函数是一个特殊的构造函数,也是用来初始化对象的,不过它是用已经存在的对象来初始化同类对象。

2. 为什么要有拷贝构造函数?

        在创建新对象时,可否用已经存在的同类对象来初始化这个新对象呢?能否快速拷贝出一个对象的副本呢?为解决以上问题,C++中引入了拷贝构造函数:拷贝构造函数用于实现对象的复制和初始化。

想要更深入的了解拷贝构造函数,可以看看博主的文章:C++ 类和对象篇(六) 拷贝构造函数


六、赋值运算符重载函数

1. 运算符重载是什么?

        运算符重载是一种在编程中扩展或改变已有运算符功能的技术。简单来说,运算符重载就是对已有的运算符重新进行定义,让运算符能够处理特定类型的对象。

2. 为什么要运算符重载?

如果想要让两个对象比较大小该怎么办?有没有办法直接使用运算符>, <来比较两个对象的大小?

class A
{
public:A(int a){num = a;}int max(A b){return num > b.num;}int operator> (A b){return num > b.num;}
private:int num;
};
int main()
{A a(10);A b(20);//如果不使用运算符重载,只能编写函数来比较两个对象的大小cout << a.max(b) << endl;//使用运算符重载cout << (a > b) << endl;return 0;
}

运算符重载的目的是为了让自定义类型能够使用运算符。
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,其目的就是让自定义类型可以像内置类型一样可以直接使用运算符进行操作。

3. 默认赋值运算符重载函数

        赋值运算符重载函数的特殊在于:只能在类中定义,用户在类中没有显式实现时,编译器会生成一个默认赋值运算符重载函数,以值的方式逐字节拷贝。注意:默认赋值运算符重载函数里内置类型成员变量是直接赋值的,而自定义类型成员变量会调用对应类的赋值运算符重载函数完成赋值:

想要更深入的了解赋值运算符重载函数,可以看看博主的文章:C++ 类和对象篇(七) 运算符重载


七、取地址运算符重载

1. 为什么需要重载取地址运算符?

        在上面分析了重载运算符的原因:为了让自定义类型能使用运算符。重载取地址运算符的目的也是如此:让自定义类型也能使用取地址运算符(&)。

2. 默认取地址运算符重载函数

        类中有6个默认成员函数,其中就有默认取地址运算符重载函数,所以即使类中没有定义取地址运算符重载函数,对象依然能使用取地址运算符(&):

3. 默认const取地址运算符重载函数

        const取地址运算符重载函数也是默认成员函数,所以即使类中没有定义取地址运算符重载函数,const对象依然能使用取地址运算符(&):

想要更深入的了解取地址运算符重载函数,可以看看博主的文章:C++ 类和对象篇(八) const成员函数和取地址运算符重载


八、默认成员函数什么情况需要显示去写?

1. 构造函数:大部分类都建议显示写一个全缺省的构造函数,除了只有自定义类型成员变量的类。

2. 析构函数:只有在类中申请了系统资源(如:使用malloc在堆上申请空间、申请文件描述符)我们才需要显示写析构函数,在析构函数中释放这些申请的系统资源。

3. 拷贝构造函数: 在堆上申请了空间的类,需要我们显示写拷贝构造函数,默认的拷贝构造函数是浅拷贝,会产生重复析构问题。

4. 赋值运算符重载函数:在堆上申请了空间的类,需要我们显示写赋值运算符重载函数,默认的赋值运算符重载函数是浅拷贝,会产生重复析构问题。

5. 取地址重载函数和const取地址重载函数:绝大多数情况下不需要显示去写,默认生成的完全够用。特殊情况下,比如不想让别人获取对象的地址,就可以自己实现,返回nullptr。

        如果一个类只有自定义类型成员变量,且自定义类型成员变量的构造、拷贝构造、赋值重载、默认析构都写好时,该类不需要显示写任何成员函数.


举个例子:当Stack类的构造、拷贝构造、赋值重载、默认析构都写好时,以下的MyQueue类的默认生成都可以用。


------------------------END-------------------------

才疏学浅,谬误难免,欢迎各位批评指正。

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

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

相关文章

win11安装双系统Ubuntu的坎坷记录

之前一直装的都是在一个硬盘中&#xff0c;这是是两块盘。 我的电脑是惠普暗影精灵8Pro 一 安装前的准备工作 1.1 记得先关闭&#xff0c;Bitlocker 输入wins&#xff0c;搜索框输入&#xff1a;设备加密设置 1.2 BIOS设置 &#xff08;惠普这电脑是开机时按 F10&#xff0…

SpringCloud(三)Sentinel、Seata、多级缓存

文章目录 Sentinel雪崩问题Sentinel与Hystrixsentinel使用案例限流规则流控模式流控效果热点参数限流 隔离和降级Feign整合Sentinel线程隔离熔断降级 授权规则与规则持续化自定义异常结果规则管理模式 Seata分布式事务问题理论基础CAP定理BASE理论 Seata架构部署TC服务微服务集…

【单片机】16-LCD1602和12864和LCD9648显示器

1.LCD显示器相关背景 1.LCD简介 &#xff08;1&#xff09;显示器&#xff0c;常见显示器&#xff1a;电视&#xff0c;电脑 &#xff08;2&#xff09;LCD&#xff08;Liquid Crystal Display&#xff09;&#xff0c;液晶显示器&#xff0c;原理介绍 &#xff08;3&#xff…

Java实现哈希表

1.哈希表定义 哈希表&#xff08;hash table&#xff0c;也叫散列表&#xff09;&#xff0c;是根据关键码值&#xff08;key value&#xff09;而直接进行访问的数据结构。也就是说&#xff0c;它通过把关键码值映射到表中一个位置来访问记录&#xff0c;以加快查找的速度。这…

浏览器唤起钉钉 各项功能

浏览器唤起钉钉对应人员聊天 文档地址 https://open.dingtalk.com/document/client/unified-routing-protocol 唤起聊天 不过只能唤起叮叮的名片 id为叮叮号 <a href"dingtalk://dingtalkclient/action/sendmsg?dingtalk_id{id}"></a>id&#xff1a; …

maven的pom.xml文件显示被删除

文章目录 1.问题情况2.问题分析3.问题解决 1.问题情况 2.问题分析 这些 pom.xml 文件被 maven 视为了忽略文件。 3.问题解决 路径&#xff1a;File --> Settings --> Build&#xff0c;Execution&#xff0c;Deployment --> Build Tools --> Maven --> Ignor…

06_Node.js服务器开发

1 服务器开发的基本概念 1.1 为什么学习服务器开发 Node.js开发属于服务器开发&#xff0c;那么作为一名前端工程师为什么需要学习服务器开发呢&#xff1f; 为什么学习服务器开发&#xff1f; 能够和后端程序员更加紧密配合网站业务逻辑前置扩宽知识视野 1.2 服务器开发可…

bochs 对 Linux0.11 进行调试 (TODO: 后面可以考虑集成 vscode+gdb+qemu)

我在阅读 Linux0.11 源码时&#xff0c;对一个指令 LDS 感到困惑。 看了下 intel 指令集手册&#xff0c;能猜到 LDS 的功能&#xff0c;但不确定。 于是决定搭建调试环境&#xff0c;看看 LDS 的功能是否真如自己猜测。 首先 make debug 运行 qemu-Linux0.11&#xff0c;命…

基于Java+SpringBoot+Vue在线家具商城系统的设计与实现 前后端分离【Java毕业设计·文档报告·代码讲解·安装调试】

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Ubuntu20.04 配置 yolov5_ros 功能包记录

文章目录 本文参考自博主源801,结合自己踩坑后修改 项目地址:https://github.com/mats-robotics/yolov5_ros 1.新建工作空间 新建一个工作空间 yolo_ros(名字可自定义),在 yolo_ros 下新建文件夹 src 并catkin_make进行编译 2. 安装相机驱动,可以选用较为主流的 usb_cam 或…

ios safari 浏览器跳转页面没有自适应

今天开发遇到了一个问题&#xff0c;当用户点击浏览器中的表单进行注册时&#xff0c;表单元素会放大&#xff0c;随后跳转页面无法还原到初始状态。 这是因为如果 的 font-size 被设定为 16px 或更大&#xff0c;那么 iOS 上的 Safari 将正常聚焦到输入表单中。但是&#xff…

2023版 STM32实战8 独立看门狗(IWDG)

IWDG简介 STM32F10xxx内置两个看门狗&#xff0c;提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障。 说人话就是能解决程序跑飞的问题。 编写代码思路 -1- 使用这个功能必须解除写保护 -2-…

FLIP动画做拖拽排序效果

先来看效果 index.html文件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content&quo…

Netty深入浅出(无处不在的IO)

为什么要有Netty Netty是为了解决网络编程的复杂性和提供易于使用、高性能和可扩展的框架而开发的。它通过提供一组可重用的组件来处理网络通信的低级细节&#xff0c;例如套接字管理、线程和缓冲&#xff0c;简化了开发网络应用程序的过程。这使开发人员可以专注于应用程序逻…

自然语言处理 | WordNet

WordNet是词汇数据库,即英语词典,专为自然语言处理而设计。 Synset是一种特殊的简单接口,存在于 NLTK 中, 用于在 WordNet 中查找单词。同义词集实例是表达相同概念的同义词的分组。有些单词只有一个同义词集,有些则有多个。

C#对字典容器Dictionary<TKey, TValue>内容进行XML序列化或反序列化报错解决方法

一、问题描述 在使用C#对字典容器Dictionary<TKey, TValue>内容进行XML序列化报错【System.Exception:“不支持类型 System.Collections.Generic.Dictionary2[[System.String, mscorlib, Version2.0.0.0, Cultureneutral, PublicKeyTokenb77a5c561934e089],[System.Strin…

基于matlab统计Excel文件一列数据中每个数字出现的频次和频率

一、需求描述 如上表所示&#xff0c;在excel文件中&#xff0c;有一列数&#xff0c;统计出该列数中&#xff0c;每个数出现的次数和频率。最后&#xff0c;将统计结果输出到新的excel文件中。 二、程序讲解 第一步&#xff1a;选择excel文件&#xff1b; [Filename, Pathn…

C++笔记之信号量、互斥量与PV操作

C笔记之信号量、互斥量与PV操作 文章目录 C笔记之信号量、互斥量与PV操作1.信号量概念2.信号量例程一3.信号量例程二4.信号量例程三5.互斥量6.PV操作概念7.PV操作详解——抄自&#xff1a;https://mp.weixin.qq.com/s/vvjhbzsWQNRkU7-b_dURlQ8.PV操作的英文全称 1.信号量概念 …

HTTPS建立连接的过程

HTTPS 协议是基于 TCP 协议的&#xff0c;因而要先建立 TCP 的连接。在这个例子中&#xff0c;TCP 的连接是在手机上的 App 和负载均衡器 SLB 之间的。 尽管中间要经过很多的路由器和交换机&#xff0c;但是 TCP 的连接是端到端的。TCP 这一层和更上层的 HTTPS 无法看到中间的包…

拼多多API接口的使用方针如下:

了解拼多多API接口 拼多多API接口是拼多多网提供的一种应用程序接口&#xff0c;允许开发者通过程序访问拼多多网站的数据和功能。通过拼多多API接口&#xff0c;开发者可以开发各种应用程序&#xff0c;如店铺管理工具、数据分析工具、购物比价工具等。在本章中&#xff0c;我…