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

news2024/9/19 21:28:40

文章目录

  • 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/432263.html

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

相关文章

Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCV实现Mono12和Mono16格式位深度的图像保存(C++)

Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCV实现Mono12和Mono16位深度的图像保存&#xff08;C&#xff09; Baumer工业相机Baumer工业相机保存位深度12/16位图像的技术背景代码案例分享1&#xff1a;引用合适的类文件2&#xff1a;BGAPI SDK在图像回调中联合OpenCV保…

Effective C++条款条款42:了解typename的双重意义(Understand the two meanings of typename)

Effective C条款条款42&#xff1a;了解typename的双重意义&#xff08;Understand the two meanings of typename&#xff09; 条款42&#xff1a;了解typename的双重意义1、从属名称和非从属名称2、typename在traits机制中的运用3、牢记 总结 《Effective C》是一本轻薄短小的…

1.17 从0开始学习Unity游戏开发--场景切换

前面的所有文章我们都在一个固定的游戏场景内进行开发&#xff0c;在最开始介绍场景这个概念的时候就已经提及&#xff0c;这个场景可以是一张地图&#xff0c;或者是一个对战房间等等&#xff0c;所以显然这个场景可以有多个&#xff0c;并且可以从一个场景切换到另外一个场景…

Collection接口

文章目录 1. Java集合框架概述2. Collection接口中15个方法的使用3. Iterator(迭代器)接口4. Connection子接口一&#xff1a;List4.1 List的实现类4.2 源码分析4.2.1 ArrayList源码分析4.2.2 LinkedList源码分析4.2.3 Vector源码分析 4.3 List接口中的常用方法 5. Collection子…

死锁---银行家算法例题

1、知识点 1.银行家算法使用的四个必要的数据结构是: 可用资源向量Available&#xff0c;最大需求矩阵Max&#xff0c;分配矩阵Allocation&#xff0c;需求矩阵Need。 2.银行家算法是不是破坏了产生死锁的必要条件来达到避免死锁的目的&#xff1f;若是&#xff0c;请简述破…

【数字 IC / FPGA】 有关建立/保持时间计算的思考

引言 最近准备一些数字IC的机试&#xff0c;刷到了一些有关静态时序分析的题目。有一些比较经典的题目&#xff0c;在这里整理分享一下。 有什么疑问可以在评论区交流~互相进步 双D触发器典型电路 假设时钟周期为Tcycle,Tsetup,Thold分别为触发器建立保持时间&#xff0c;为…

Mac OS挂载ext4硬盘

一、安装macFUSE Home - macFUSE 如下载macfuse-4.4.3dmg安装 安装过程可能会遇到“若要要启用系统扩展,您需要在恢复环境中修改安全性设置”的提示&#xff0c;如下图&#xff1a; 解决&#xff1a; 关机&#xff0c;直到键盘灯全灭了&#xff01; 再按住开机键&#xff0c…

机器视觉技术分享-彩色图像处理 含c++ ,python代码说明

彩色图像处理是指对彩色图像进行数字处理和分析的过程&#xff0c;其目的是提取图像的有用信息&#xff0c;改善图像质量&#xff0c;实现图像的增强、复原、分割、匹配、识别等功能。 针对彩色图像处理&#xff0c;可以采用以下一些常见的方法&#xff1a; 1. 颜色空间转换&…

简简单单认识一下Inscode

CSDN最新推出的Inscode服务是一个在线编程工具&#xff0c;旨在为开发者提供一个便捷的编写、运行和分享代码的环境&#xff0c;让开发者无需在本地搭建编程环境&#xff0c;即可快速编写和运行代码。 Inscode支持多种编程语言&#xff0c;包括Java、Python、C等&#xff0c;同…

C语言进阶之回调函数详解分析方法

一、函数指针 在讲回调函数之前&#xff0c;我们需要了解函数指针。 我们都知道&#xff0c;C语言的灵魂是指针&#xff0c;我们经常使用整型指针&#xff0c;字符串指针&#xff0c;结构体指针等。 int *p1; char *p2; STRUCT *p3; // STRUCT为我们定义的结构体 但是好像我…

PlumGPT【告别梯子,拥抱AI】

相信很多人苦于没有openai账号或者有着种种原因至今还没有使用过chatgpt&#xff0c;今天向大家推荐一个网站&#xff0c;在国内也可以任意方便使用&#xff0c;让你的办公效率最大化。 那就是PlumGPT&#xff1a;https://plumgpt.com/ PlumGPT&#xff08;国内版的chatgpt&a…

Mybatis分页实现

1. Rowbounds Rowbounds将所有符合条件的数据加载到内存&#xff0c;然后再实现逻辑切割。 Override public List<User> getAllUser() {RowBounds rowBounds new RowBounds(1, 2);return userMapper.getAllUser(rowBounds); }查询sql&#xff08;没有任何分页逻辑&…

【Redis】常用命令、各种数据结构及命令

目录 一、常见数据结构 二、常用命令 1、查询符合的所有key 2、删除key 3、判断key是否存在 4、给key设置过期时间 5、查看key的剩余过期时间 三、不同数据类型的操作命令 1、String 1.set 2.get 3.mset 4.mget 5.incr 6.incrby 7.incrbyfloat 8.setnx 9.se…

C++——内存分配与动态内存管理

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;C/C内存分布&#x1f33a;牛刀小试&#x1f33a;C语言动态内存管理&#x1f337;C动态内存管理&#x1f33a;对于内置类型&#x1f33a;对于自定义类型&#x1f337;operator new与operator delete函数&#x…

便携式明渠流量计有哪几种呢?

便携式明渠流量计有几种&#xff1f; 目前来说市面上是有两种&#xff0c;但最终的作用或者说是功能都是用来和明渠在线流量计做液位和流量比对的一种装置。 这两种有什么区别呢&#xff1f; 一种就是便携式明渠流量计磁致伸缩流量计&#xff0c;另一种就是便携式明渠超声波…

浅析EasyCVR基于B/S架构的技术特点与能力应用

EasyCVR基于云边端协同&#xff0c;可支持海量视频的轻量化接入与汇聚管理。平台兼容性强、拓展度高&#xff0c;可提供视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联等功能。 EasyCVR视频融合平台采用…

【MyBatis Plus】004 -- MyBatis Plus高级(AR、MP插件、自定义全局操作、自动填充、逻辑删除、枚举、代码生成器)

目录 1、ActiveRecord 1.1 开启AR之旅&#xff08;根据主键 id 进行查询&#xff09; 1.2 新增数据 1.3 更新操作 1.4 删除操作 1.5 根据条件查询 2、Oracle 主键 Sequence 2.1 部署Oracle环境 2.2 创建表以及序列 2.3 jdbc驱动包 2.4 修改application.properties 2.5 配置序列…

LC-1041 困于环中的机器人(模拟,快慢指针找环)

1041. 困于环中的机器人 难度中等148 在无限的平面上&#xff0c;机器人最初位于 (0, 0) 处&#xff0c;面朝北方。注意: 北方向 是y轴的正方向。南方向 是y轴的负方向。东方向 是x轴的正方向。西方向 是x轴的负方向。 机器人可以接受下列三条指令之一&#xff1a; "…

第一讲 初识Python

Python简介 Python&#xff08;英式发音&#xff1a;/ˈpaɪθən/&#xff1b;美式发音&#xff1a;/ˈpaɪθɑːn/&#xff09;是由荷兰人吉多范罗苏姆&#xff08;Guido von Rossum&#xff09;发明的一种编程语言&#xff0c;是目前世界上最受欢迎和拥有最多用户群体的编…

【Colab】Colab使用教程(跑本地文件)

文章目录前言一、上传本地文件二、Colaboratory使用1、连接2、调整文件3、运行文件三、未来可期前言 首先&#xff0c;自己想办法注册谷歌账号&#xff0c;本文不讲。 Colaboratory网址&#xff1a;https://colab.research.google.com/ 谷歌云端硬盘&#xff1a;https://dri…