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.rhkb.cn/news/152827.html

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

相关文章

Windows环境下下载安装Elasticsearch和Kibana

Windows环境下下载安装Elasticsearch和Kibana 首先说明这里选择的版本都是7.17 &#xff0c;为什么不选择新版本&#xff0c;新版本有很多坑&#xff0c;要去踩&#xff0c;就用7就够了。 Elasticsearch下载 Elasticsearch是一个开源的分布式搜索和分析引擎&#xff0c;最初由…

【FreeRTOS】【STM32】01从零开始的freertos之旅 浏览源码下的文件夹

基于野火以及正点原子 在打开正点原子的资料pdf时&#xff0c;我遇到了pdf无法复制粘贴的问题&#xff0c;这里有个pdf解锁文字复制功能的网址&#xff0c;mark一下。超级pdf 参考资料《STM32F429FreeRTOS开发手册_V1.2》 官方资料 FreeRTOS 的源码和相应的官方书籍均可从官…

cap分布式理论

cap 理论 cap是实现分布式系统的思想。 由3个元素组成。 Consistency&#xff08;一致性&#xff09; 在任何对等 server 上读取的数据都是最新版&#xff0c;不会读取出旧数据。比如 zookeeper 集群&#xff0c;从任何一台节点读取出来的数据是一致的。 Availability&…

Go 复合类型之切片类型介绍

Go 复合类型之切片类型 文章目录 Go 复合类型之切片类型一、引入二、切片(Slice)概述2.1 基本介绍2.2 特点2.3 切片与数组的区别 三、 切片声明与初始化3.1 方式一&#xff1a;使用切片字面量初始化3.2 方式二&#xff1a;使用make函数初始化3.3 方式三&#xff1a;基于数组的切…

使用企业订货系统后的效果|软件定制开发|APP小程序搭建

使用企业订货系统后的效果|软件定制开发|APP小程序搭建 企业订货系统是一种高效的采购管理系统&#xff0c;它可以帮助企业更好地管理采购流程&#xff0c;降低采购成本&#xff0c;提高采购效率。 可以帮助企业提高销售效率和降低成本的软件工具。使用该系统后&#xff0c;企业…

《DevOps 精要:业务视角》- 读书笔记(二)

DevOps 精要:业务视角&#xff08;二&#xff09; 第2章 基础2.1 精益生产2.1.1 关键事实2.1.2 挑战 2.2 敏捷2.2.1 关键事实2.2.2 挑战 第2章 基础 2.1 精益生产 2.1.1 关键事实 正如1.2节提到的&#xff0c;DevOps非常依赖于精益生产的原则与实践。有些人甚至相信&#xf…

R语言快速实现图片布局(1)

&#xff08;1&#xff09;简单的一排或者对称的多排&#xff0c;使用patchwork即可。/表示分行&#xff0c;|表示分列 library(patchwork) pp1<-ggplot(mtcars) geom_point(aes(mpg, disp)) pp2<-ggplot(mtcars) geom_boxplot(aes(gear, disp, group gear)) pp3 <…

08_selenium实战——学习平台公开数据批量获取

0、:前言 该实战任务是对某视频平台中’标题’、 ‘点赞数量’、 ‘投币数量’、‘收藏数量’、‘播放次数’、以及前五条评论进行爬取。要求1:可以控制爬取视频的主题(爬取主题搜索之后的内容)要求2:可以控制爬取视频的数量要求3:对于评论数不足5条的用0填充评论内容爬虫…

Eclipse iceoryx™ - 真正的零拷贝进程间通信

1 序言 通过一个快速的背景教程&#xff0c;介绍项目范围和安装所需的所有内容以及第一个运行示例。 首先&#xff1a;什么是冰羚&#xff1f; iceoryx是一个用于各种操作系统的进程间通信&#xff08;IPC&#xff09;中间件&#xff08;目前我们支持Linux、macOS、QNX、FreeBS…

MongoDB——centOS7安装mongodb5.0.21版本服务端(图解版)

目录 一、mongodb官网下载地址二、安装步骤2.1、上传安装包并解压2.2、配置环境变量2.3、创建目录并授权2.4、创建配置文件2.5、启动MongoDB 三、开放端口四、客户端连接 一、mongodb官网下载地址 mongodb官网下载地址&#xff1a;https://www.mongodb.com/try/download/commu…

MySQL-锁

MySQL的锁机制 1.共享锁(Shared Lock)和排他锁(Exclusive Lock) 事务不能同时具有行共享锁和排他锁&#xff0c;如果事务想要获取排他锁&#xff0c;前提是行没有共享锁和排他锁。而共享锁&#xff0c;只要行没有排他锁都能获取到。 手动开启共享锁/排他锁&#xff1a; -- 对…

更新Xcode 版本后运行项目出现错误 Unable to boot the Simulator 解决方法

错误截图 出现 Unable to boot the Simulator 错误原因很多&#xff0c;以下方法不一定都适用&#xff0c;我是通过以下方法解决的 打开命令终端输入以下命令&#xff0c;可能需要你输入开机密码 sudo rm -rf ~/Library/Developer/CoreSimulator/Caches

Linux知识点 -- 网络基础 -- 数据链路层

Linux知识点 – 网络基础 – 数据链路层 文章目录 Linux知识点 -- 网络基础 -- 数据链路层一、数据链路层1.以太网2.以太网帧格式3.重谈局域网原理4.MAC地址5.MTU6.查看硬件地址和MTU的命令7.ARP协议 二、其他重要协议或技术1.DNS&#xff08;Domain Name System&#xff09;2.…

css记录写一个奇怪的按钮

完成作业的时候发现一个很有意思的按钮&#xff0c;记录一下记录一下 看看界面 可以看出是一个奇形怪状的按钮&#xff0c;而且在按下的时候&#xff0c;图片和文字的颜色会改变 尝试解决 <!DOCTYPE html> <html lang"zh"> <head><meta chars…

vue3+elementPlus:el-tree复制粘贴数据功能,并且有弹窗组件

在tree控件里添加contextmenu属性表示右键点击事件。 因右键自定义菜单事件需要获取当前点击的位置&#xff0c;所以此处绑定动态样式来控制菜单实时跟踪鼠标右键点击位置。 //html <div class"box-list"><el-tree ref"treeRef" node-key"id…

一篇短小精悍的文章让你彻底明白KMP算法中next数组的原理

以后保持每日一更&#xff0c;由于兴趣较多&#xff0c;更新内容不限于数据结构&#xff0c;计算机组成原理&#xff0c;数论&#xff0c;拓扑学......&#xff0c;所谓&#xff1a;深度围绕职业发展&#xff0c;广度围绕兴趣爱好。往下看今日内容 一.什么是KMP算法 KMP&#x…

【垃圾回收概述及算法】

文章目录 1. 垃圾回收概述及算法2. 垃圾回收相关算法2.1 标记阶段&#xff1a;引用计数算法2.2 标记阶段&#xff1a;可达性分析算法2.3 对象的 finalization 机制2.3.1 一个对象是否可回收的判断 2.4 清除阶段&#xff1a;标记-清除算法2.5 清除阶段&#xff1a;复制算法2.6 清…

【苍穹外卖 | 项目日记】第一天

前言&#xff1a; 我打算用16天的时间写完黑马程序员的苍穹外卖项目&#xff0c;为了督促自己每天坚持写以及记录项目知识点&#xff0c;所以用这种项目日记的方式鞭策自己 目录 前言&#xff1a; 今日完结任务&#xff1a; 今日收获&#xff1a; 1.阅读代码框架&#xf…

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…

QQ浏览器怎么才能设置默认搜索引擎为百度

问题&#xff1a; 打开QQ浏览器&#xff0c;搜索相关信息时发现总是默认为”搜狗搜索引擎“&#xff0c;想将其转为”百度搜索引擎“ 解决&#xff1a; 1、点击浏览器右侧”菜单“图标&#xff0c;选择”设置“&#xff0c;如下图所示&#xff1a; 2、在”常规设置“中的”搜…