C++ -3- 类和对象 (中) | 拷贝构造函数 赋值运算符重载(二)

news2024/11/16 0:22:02

文章目录

  • 4.拷贝构造函数
    • 什么是拷贝构造函数?
    • 应用——示例:日期计算器
    • 什么情况下需要自己实现拷贝构造函数?
  • 5.赋值运算符重载
    • 运算符重载(重要)
    • 赋值运算符重载
  • 拷贝构造函数和赋值重载函数


4.拷贝构造函数

什么是拷贝构造函数?

  • 示例:
class Date
{
public:
	//构造函数
	Date(int year=2023,int month=2,int day=27){
		_year = year;
		_month = month;
		_day = day;
	}

	//拷贝构造函数
	Date(Date d)
	{……}
	
private:
	int _year;
	int _month;
	int _day;
};

void TestDate1(){
	Date d1(2023, 4, 1);//调用构造函数
	Date d2(d1);//调用拷贝构造函数
	//or
	Date d2 = d1;//调用拷贝构造函数
}

拷贝初始化构造函数的作用是将一个已知对象的数据成员值拷贝给正在创建的另一个同类的对象

  • 无穷递归Date(Date d){……}
    • 首先,分析传值传参的过程
      在这里插入图片描述

    • 传引用传参没有拷贝的过程,直接传

    • 传值传参:
      内置类型编译器可以直接拷贝(浅拷贝/值拷贝——一个字节一个字节的拷贝)
      自定义类型编译器无法拷贝,需要调用 拷贝构造函数(浅拷贝 or 深拷贝)

    • 为什么会无穷递归:
      在这里插入图片描述

∴ 正确的拷贝构造: 传引用传参

//拷贝构造函数
Date(const Date& d)
{	//……	
}

应用——示例:日期计算器

日期计算器:实现一个函数,获取 X 天后的日期
第一种:

int GetMonthDay(int year, int month)//获取对应年月的天数
{
	if (month > 0 && month < 13)
	{
		int array[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (month == 2)
		{

			if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
			{
				++array[2];
			}
		}

		return array[month];
	}
	else
	{
		cout << "month error" << endl;
		return 0;
	}
}

class Date
{
public:
	//构造函数
	Date(int year = 2023, int month = 2, int day = 27)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	//拷贝构造函数
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

	//获取 X 天后的日期
	Date& GetAfterXDate1(int x)
	{
		_day = _day + x;
		int monthDay = GetMonthDay(_year, _month);
		while (_day > monthDay)
		{
			_day -= monthDay;
			++_month;

			if (_month > 12)
			{
				++_year;
				_month = 1;
			}
			monthDay = GetMonthDay(_year, _month);

		}
		return *this;//调用拷贝构造
	}

private:
	int _year;
	int _month;
	int _day;
};

void TestDate1()
{
	Date d1(2023, 4, 1);
	d1.GetAfterXDate1(10000);
	d1.Print();
}

第二种:不改变原日期

//获取 X 天后的日期
Date GetAfterXDate2(int x)
{
	Date tmp = *this;//调用拷贝构造
	tmp._day = _day + x;
	int monthDay = GetMonthDay(tmp._year, tmp._month);
	while (tmp._day > monthDay)
	{
		tmp._day -= monthDay;
		++tmp._month;
		if (tmp._month > 12)
		{
			++tmp._year;
			tmp._month = 1;
		}
		monthDay = GetMonthDay(tmp._year, tmp._month);
	}
	return tmp;//调用拷贝构造
}
void TestDate2()
{
	Date d1(2023, 4, 1);
	Date d2 = d1.GetAfterXDate2(10000);
}
  • 拷贝构造函数也是特殊的成员函数,其特征如下:
  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
  3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做 浅拷贝,或者 值拷贝

什么情况下需要自己实现拷贝构造函数?

  • 编译器默认的拷贝构造函数 能完成“值拷贝”(浅拷贝)
    所以,日期类(都是内置类型)没有自己实现拷贝构造函数的必要

  • 什么情况下需要自己实现拷贝构造函数?
    在这里插入图片描述

  • sum. 自己实现了析构函数释放空间(意味着设计资源管理),则需要自己实现拷贝构造函数


5.赋值运算符重载

运算符重载(重要)

运算符重载:让【自定义类型】可以使用运算符

例如: 内置类型可以直接比大小;自定义类型不可以直接比大小

//内置类型
int a = 1,b = 2; a==b; a>b;

//自定义类型
class Date { 	//…… } 
Date d1;Date d2; 
d1==d2;? d1<d2;?

运算符重载具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型:返回值类型 operator操作符(参数列表)

  • 将运算符重载函数放在全局:
bool operator==(const Date& d1,const Date& d1)
{
	return d1._day == d2._day
		&& d1._month == d2._month
		&& d1._year == d2._year;
}
  • 将运算符重载函数放入类:
    • 这里需要注意的是,左操作数是this,指向调用函数的对象
    • 操作符使用时包含几个操作数,运算符重载函数就含有几个参数
bool operator==(Date* this, const Date& d2)
!这里需要注意的是,左操作数是this,指向调用函数的对象
----------------------------------------------
// ==运算符重载
bool Date::operator==(const Date& d)
{
	return _day == d._day
		&& _month == d._month
		&& _year == d._year;
}
// >运算符重载
bool Date::operator>(const Date& d)
{
	if (_year < d._year)
		return false;
	if (_year > d._year)
		return true;
	if (_month < d._month)
		return false;
	if (_month > d._month)
		return true;
	if (_day < d._day)
		return false;
	if (_day > d._day)
		return true;
		
	return false;
}

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个 类型 参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* / :: / sizeof / ?: / .注意以上5个运算符不能重载。

赋值运算符重载

1.赋值运算符重载的特性

赋值运算符 “=”,可以连续赋值,例如:

int i = 1,j = 0,k = 0;
j = k = i;//连续赋值

∴ 赋值运算符重载函数应该有 返回值

// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{
	if (*this == d)//如果时自己给自己赋值就不用进行下列操作了
		return *this;
	_day = d._day;
	_month = d._month;
	_year = d._year;
	return *this;
}
  1. 赋值运算符只能重载成类的成员函数不能重载成全局函数

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。


拷贝构造函数和赋值重载函数

默认生成的拷贝函数/赋值重载函数

  1. 内置类型浅拷贝
  2. 自定义类型,调用这个成员的拷贝构造函数/赋值重载函数

对比↕

默认生成的构造函数/析构函数

  1. 内置类型不处理
  2. 自定义类型,调用它的默认构造函数

END

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

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

相关文章

【进阶C语言】静态版通讯录的实现(详细讲解+全部源码)

前言 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;正在学习C/C、Java、Python等。 &#x1f4d7;本文收录于C语言进阶系列&#xff0c;本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数的介绍、自定义类型结构、动态内存管理、文件操作等&#xff0…

Javaee Spring JdbcTemplate基本使用查询数据库表的内容 基于xml配置方式

目录 哈哈哈哈&#xff0c;说好是要写一篇关于jdbcTemplate的基本使用&#xff0c;貌似说跑题了&#xff0c;但是主体还是用jdbctemplate实现的&#xff0c;有耐心看完的话相信能有点点收获的哦&#xff01; 项目结构&#xff1a; 用到的数据库: 小结&#xff1a; 遇到了个小…

【Python_Opencv图像处理框架】图像基本操作

写在前面 很幸运能选择Python语言进行学习&#xff0c;这是有关Opencv的图像处理的第一篇文章&#xff0c;讲解了有关图像处理的一些基础操作&#xff0c;作为初学者&#xff0c;我尽己所能&#xff0c;但仍会存在疏漏的地方&#xff0c;希望各位看官不吝指正❤️ 写在中间 1…

Docker容器---介绍、安装

Docker基本管理 一、Docker概述1、IT架构2、什么是docker3、Docker特点4、Docker与KVM区别 二、Docker核心概念1、镜像 容器 仓库2、虚拟架构有哪些 三、Docker使用场景1、Docker在内核中支持的2种重要技术2、应用场景 四、Docker安装1、YUM安装docker2、设置阿里云镜像源3、查…

Java多线程初阶(一)(图片+源码+超详细)

线程的概念参照以往的这篇文章&#x1f43b; 目录 1.创建线程 1.1 继承Thread类 1.2 实现Runnable接口 eg&#xff1a;常用的简写方式 2.Thread类中的常用API 3. start方法和run方法 4. 继承Thread类启动新线程的逻辑 5. 实现Runnable接口启动新线程的逻辑 6. 线程相关…

Linux基础—日志分析

Linux基础—日志分析 一、日志的功能1.日志消息的级别2.设备字段说明 二、日志文件的分类1.内核及系统日志2.用户日志3.程序日志 三、日志文件1.日志文件查看2.主要日志文件介绍3.日志管理策略 一、日志的功能 用于记录系统、程序运行中发生的各种事件 通过阅读日志&#xff0c…

图像描述算法排位赛:SceneXplain与MiniGPT-4谁将夺得桂冠?

如果你对 AI 前沿感兴趣&#xff0c;本场「图像描述算法排位赛」绝对是你不能错过的&#xff01;在这场较量中&#xff0c;SceneXplain 和 MiniGPT-4 将会比试&#xff0c;谁将摘得这场比赛的桂冠&#xff1f; &#x1f4ce; 直接上手体验&#xff1a;scenex.jina.ai 背景介绍 …

手机存储数据恢复软件哪个好用?试了10款,我只认准这一款!

案例&#xff1a;手机存储数据恢复软件哪个好用&#xff1f; 【有没有好介绍的苹果数据恢复软件&#xff1f;可以恢复好几年数据的那种软件&#xff1f;求推荐&#xff01;】 手机中的数据是用户平时使用手机时不可避免的内容&#xff0c;这些数据包括照片、视频、音乐、文件等…

Baumer工业相机堡盟工业相机如何通过BGAPISDK的软触发实现两相机同步采集(C++)

Baumer工业相机堡盟工业相机如何通过BGAPISDK的软触发实现两相机的同步采集&#xff08;C&#xff09; Baumer工业相机Baumer工业相机的高速同步采集的技术背景Baumer工业相机通过BGAPI SDK在回调函数里同步保存图像工业相机在回调函数BufferEvent保存工业相机使用软触发进行同…

【观察】华为:新一代楼宇网络,使能绿建智慧化

“碳达峰”、“碳中和”目标是我国生态文明建设和高质量可持续发展的重要战略安排&#xff0c;将推动全社会加速向绿色低碳转型。作为全球既有建筑和每年新建建筑量最大的国家&#xff0c;大力发展绿色建筑对中国全方位迈向低碳社会、实现高质量发展具有重要意义。 《“十四五”…

使用FirmAE 对zyxel路由器固件仿真实践 | 信息安全

一、FirmAE简介 FirmAE 是一个执行仿真和漏洞分析的全自动框架。FirmAE 使用五种仲裁技术显著提高仿真成功率&#xff08;从Firmadyne的 16.28% 提高到 79.36%&#xff09;。 FirmAE的整体架构为如上图所示。与Firmadyne类似&#xff0c;FirmAE在预先构建的自定义Linux内核和库…

Codeforces Round 816 (Div. 2)(C. Monoblock)

传送门 题意&#xff1a; 定义一个数组&#xff0c;定义它 相等连续段的个数 如1,2,2,1&#xff0c;相等连续段有[1],[2,2],[1]&#xff0c;共3个 如2,2,2,1&#xff0c;相等连续段有[2,2,2],[1]&#xff0c;共2个 给定一个数组a&#xff0c;定义g(l,r)为&#xff0c;子数组中…

fisco bcos 2.0+ 版本浏览器搭建

Fisco Bcos当前已经发布了3版本&#xff0c;在3版本中&#xff0c;Fisco摒弃了原有的区块链浏览器&#xff0c;而是提供了具有更为丰富功能的图形化区块链管理工具WeBase&#xff0c;后续也会提供对于WeBase的搭建部署教程。 文章目录 一、准备条件二、下载浏览器安装脚本1. 下…

ChatGPT4 的体验 一站式 AI工具箱 -—Poe(使用教程)

最近由于人工智能聊天机器人的爆火(ChatGPT)&#xff0c;因此各种各样的AI助手流行与网络&#xff0c;各种各样的都有&#xff0c;不论是什么样的其实都是为了我们更方便的解决问题&#xff0c;今天介绍一款AI工具箱——Poe将多种AI集成与一个界面&#xff0c;大家可以一次感受…

Mac系统brew报错“The GitHub credentials in the macOS keychain may be invalid”解决

报错信息如下&#xff1a; $ brew search nginx Warning: Error searching on GitHub: GitHub API Error: Requires authentication The GitHub credentials in the macOS keychain may be invalid. Clear them with: printf "protocolhttps\nhostgithub.com\n" | …

Python双向链表的操作

目录 一、双向链表 双向链表示例图 二、双向链表的操作 1、判断链表是否为空 2&#xff0c;链表长度 3&#xff0c;遍历整个链表 4&#xff0c;在链表头部添加元素 5、链表尾部添加元素 6&#xff0c;在指定位置插入元素 7&#xff0c;修改指定位置的元素 8&#xff0…

百度ai智能写作工具-百度ai自动写文章

百度AI智能写作工具&#xff1a;让创作更快捷、高效&#xff01; 在当今竞争激烈的文化创意市场中&#xff0c;创作一篇高质量的文章需要投入大量时间和精力。然而&#xff0c;有了百度AI智能写作工具&#xff0c;创作变得更快捷、高效了。 百度AI智能写作工具采用最先进的人…

JVM之垃圾回收器概述

目录 垃圾收集器分类 按线程数分 按照工作模式分 ​编辑 按碎片处理方式分 按工作的内存区间分 评估GC的性能指标 吞吐量 暂停时间 吞吐量 vs 暂停时间 垃圾回收器概述 垃圾收集器没有在规范中进行过多的规定&#xff0c;可以由不同的厂商、不同版本的JVM来实现。 由…

一起学 WebGL:感受三维世界之视图矩阵

大家好&#xff0c;我是前端西瓜哥。之前绘制的图形都是在 XY 轴所在的平面上&#xff0c;这次我们来加入一点深度信息 z&#xff0c;带你走入三维的世界。 视图矩阵 对于一个立方体来说&#xff0c;我们从它的正前方看&#xff0c;不管距离它多远&#xff0c;也只能看到一个…

微服务下网关聚合Swagger文档、starter统一配置Swagger

一、starter实现统一配置微服务文档 把Swagger配置中的公共部分抽取出来Swagger与SpringBoot整合中&#xff0c;可能会由于版本问题出现各种问题 1、制作starter 参考&#xff1a; 【SpringBoot】自定义启动器 Starter【保姆级教程】用starter实现Oauth2中资源服务的统一配置用…