C嘎嘎~~ [类 下篇(2)]

news2024/11/23 12:42:19

类 下篇2

  • 5.赋值运算符重载
    • 5.1运算符重载
      • 5.1.1 运算符的概念
      • 5..1.2 重载运费符的位置
      • 5.1.3运算符重载的实质
    • 5.2 赋值运算符重载
      • 5.2.1深刻理解---编译器生成的默认赋值运算符重载
      • 5.2.2深刻理解---拷贝构造和赋值运算符重载
      • 5.2.3深刻理解---传参和返回值用引用修饰

5.赋值运算符重载

5.1运算符重载

5.1.1 运算符的概念

C语言学习的时候, 我们可以用运算符来操作内置类型. 比如, 比较两个整数的大小, 比较两个整数是否想相等… …
那么我们能不能也用操作符来对自定义类型来进行操作??

class Date
{

public:

	Date(int year = 2023, int month = 5, int day = 5)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

int main()
{
	Date d1(2023, 5, 6);
	Date d2(2003, 5, 7);

	bool ret = d1 > d2;
}

*****
error C2676: 二进制“>:“Date”不定义该运算符或到预定义运算符可接收的类型的转换
*****

通过上面的代码, 我们可以发现是不行的~~.
其实, 不用代码来作佐证, 我们也可以猜想的出来 <== 因为不知道要比较什么啊. 到底是比较两个对象的年, 还是比较两个对象的月, 还是比较两个对象的日??
由此, 我们可以基本得出 ⇒ 内置类型可以直接使用操作符, 而自定义类型只能自己来写~~(当然, 这个有一个是意外的, 就是后面要讲的 赋值运算符重载)

为了解决自定义类型的 操作符使用, 引入了operator 这个关键字. operator + 操作符 ⇒ 就会导致该操作符重载

C++为了增强代码 的可读性引入了运算符重载, 运算符重载是具有特殊函数名的函数.

  • 函数的一般形式: 返回值类型 + operator + 操作符 (参数列表)
  • 函数是可以具有返回值类型的, 函数名, 以及参数列表

注意点:

  1. 不能创造新的操作符 , 比如 operator @
  2. 操作数至少有一个自定义类型 ⇐ 因为操作符重载就是用于自定义类型的, 如果都是内置类型, 我们就不用且不能改变, 编译器已经自己完成.
  3. 作为成员函数时, 形参比原本的操作数少一个⇐ 因为作为成员函数, 第一个形参就已经确定了, 就是this指针, 然而this指针是不在参数列表中显示的
  4. 名字虽然是重载, 但是这个重载却跟函数重载的重载不是一个意思. 这个重载的意思是: 让用户更加直观地知道这个运算符是等同功能作用于自定义类型的.
  5. 运算符重载函数是可以构成重载的
  6. 有五个操作符是不可以进行运算符重载的, .*(这个是 点乘, 不知道有啥用)) ::(作用域限定域) sizeof(计算变量 或 类型的大小) ?:(三目运算符) .(访问符)

5…1.2 重载运费符的位置

一般来说, 重载运费符函数是可以放在类中充当成员函数的, 也可以直接放在全局变量中的

  1. 重载运费符在全局变量
class Date
{

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

bool operator== (const Date& x1, const Date& x2)
{
	if (x1._year == x2._year && x1._month == x2._month && x1._day == x2._day)
		return true;

	return false;
}

int main()
{
	Date d1(2023, 5, 6);
	Date d2(2003, 5, 7);

	bool ret = d1 == d2;
	cout << ret << endl;

}

*****
0
*****
  1. 重载运算符在类中
class Date
{

public:

	bool operator==(const Date& x)
	{
		if (_year == x._year && _month == x._month && _day == x._day)
			return true;

		return false;
	}

	// 构造函数
	Date(int year = 2023, int month = 5, int day = 5)
	{
		_year = year;
		_month = month;
		_day = day;
	}


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


int main()
{
	Date d1(2023, 5, 6);
	Date d2(2003, 5, 7);

	bool ret = d1 == d2;
	cout << ret << endl;

}

*****
0
*****

通过上面两组代码的对比, 我们可以发现:

  1. 相比较写在全局变量中, 充当成员函数, 我们就用少写一个操作数
  2. 写在全局变量中, 我们就不能用对象去访问类中的私有变量(我把私有放开了~)
  3. 其实, 用对象去访问私用变量有两种方式: 一是充当成员函数, 二是用友元函数(这个建议能不用就不用, 会破坏封装的)

5.1.3运算符重载的实质

我们已经知道的是用内置类型使用操作符是将 例如 " a > b"这样的操作符抓换成指令.
那么, 我们使用运算符重载的实质又是什么??

前面, 我们已经知道运算符重载是用函数来实现的, 我们就大胆猜想⇒ 使用运算符重载的实质就是调用函数


通过上面的佐证, 我们发现了 使用运算符重载 和 调用函数 的指令是一样的 ⇒ 使用运算符重载的实质就是调用函数


5.2 赋值运算符重载

有些老铁就有疑问: 我们之前的默认成员函数不是还没有讲完嘛, 怎么又讲这个运算符重载??
在日常的应用中, 赋值是非常常见的 ⇒ 所以赋值运算符是一个默认成员函数
运算符重载就是 为下面的赋值运算符重载打基础的~~

赋值运算符重载的格式:

  • 参数类型: const 类名&, 传递引用可以提高效率
  • 返回值类型: 为了支持连续赋值, 返回类类型; 建议返回类型传引用, 也是提高效率
  • 返回 *this: 也是为了支持连续赋值
  • 也要注意是否自己给自己赋值
  • 普通的运算符重载的位置可以是在全局变量中的, 但是赋值运算符重载只能充当成员函数⇐ 因为它是默认成员函数, 如果写在外面 会和编译器生成的默认赋值运算符重载构成歧义.

5.2.1深刻理解—编译器生成的默认赋值运算符重载

编译器默认生成的运算符重载的行为 跟 编译器默认生成的默认拷贝构造函数是一样的
对内置类型: 按内存字节去拷贝, 相当于memcpy, 是浅拷贝, 也叫值拷贝
对自定义类型: 会调用自己的拷贝构造函数

处理:
对于没有资源申请的类型: 可以使用编译器默认生成的赋值运算符重载
对于有资源申请的类型: 自己来写一个赋值运算符重载函数

5.2.2深刻理解—拷贝构造和赋值运算符重载

拷贝构造: 用一个对象去初始化另一个对象(就是在对象实例化的时候, 直接初始化)
赋值运算符重载: 已经存在的,两个对象的复制

class Date
{
public:
	// 赋值运算符重载
	Date operator=(const Date& x)
	{
		if (this != &x)
		{
			_year = x._year;
			_month = x._month;
			_day = x._day;
		}

		return *this;
	}

	Date(int year = 2023, int month = 5, int day = 5)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

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

int main()
{
	// 构造
	Date d1(2023,5,9);
	Date d4;
	d1.Print(); // 2023 5 9
	d4.Print(); // 2023 5 5 

	// 拷贝构造
	Date d2(d1);
	Date d3 = d1;
	d2.Print(); // 2023 5 9
	d3.Print(); // 2023 5 9

	// 赋值运算符重载
	d1 = d4;
	d1.Print(); // 2023 5 5
	d4.Print(); // 2023 5 5

}

有人就会有疑问: d3 = d1 为什么是拷贝构造啊? 明明用的就是赋值啊?
抓重点: 拷贝构造就是初始化对象啊, 赋值就是两个已存在的对象之间的操作~~


5.2.3深刻理解—传参和返回值用引用修饰

class Date
{
public:
	// 赋值运算符重载
	Date& operator=(const Date& x)
	{
		if (this != &x)
		{
			_year = x._year;
			_month = x._month;
			_day = x._day;
		}

		return *this;
	}

	Date(int year = 2023, int month = 5, int day = 5)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

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

int main()
{
	Date d1(2023, 5, 6);
	Date d2(2003, 5, 7);
	Date d3;

	d1 = d2 = d3;
	d1.Print();
	d2.Print();
	d3.Print();
}

*****
2023 5 5
2023 5 5 
2023 5 5

*****

相信大家应该还记得 自定义类型传参和赋值是会自动调用拷贝构造的, 如果我们不写拷贝构造函数, 将会使用浅拷贝.
如果我们返回的是一个引用的话, 就不会生成一个临时拷贝, 那么也就不会调用拷贝构造~~


誓言是世界上最靠不住的东西,只有你对别人还有用的时候,别人才会遵守誓言。

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

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

相关文章

ADAS-透视前方:汽车HUD技术原理解析

“ 当人们谈论未来的汽车技术时&#xff0c;汽车HUD&#xff08;Head-Up Display&#xff09;是一个经常被提及的技术。HUD是一种驾驶辅助技术&#xff0c;它可以将关键的驾驶信息直接显示在驾驶员的视线范围内&#xff0c;让驾驶员无需转移视线就能获得所需信息。这个技术在过…

HZNUCTF2023 web

目录 <1> guessguessguess <2> ezflask(无过滤ssti) ​ <3> ppppop(cookie泄露反序列化) <4> ezlogin(bool盲注) <5> ezpickle(pickle反序列化) <6> eznode(原型链污染) <1> guessguessguess 尝试是否存在sql注入&#xff0c;…

03- 目标检测数据集和标注工具介绍 (目标检测)

要点&#xff1a; 常用数据集和标注工具 标注工具 PPOCRLabel github地址&#xff1a;paddleocrlabel 参考文档&#xff1a;目标检测简介 - 知乎 一 目标检测数据集 1. PASCAL VOC VOC数据集是目标检测经常用的一个数据集&#xff0c;自2005年起每年举办一次比赛&#xff…

JWT快速入门及日常使用

什么是JWT JSON Web Token&#xff0c;通过数字签名的方式&#xff0c;以json对象为载体&#xff0c;在不同服务端之间安全的传输信息 JWT有什么用 JWT最常见的场景就是授权认证&#xff0c;一旦用户登录&#xff0c;后续每个请求都将包含JWT&#xff0c;系统每次处理用户请求前…

总结下自己编译alembic的过程

编译alembic过程回顾 前言 总结下自己编译alembic的过程 最近想学习编译啥的&#xff0c;就想着一边编译着&#xff0c;一边学习的&#xff0c;刚好&#xff0c;拿alembic编译练手&#xff0c;记录下自己编译的过程吧。 编译的使用的是Visual Studio 2022&#xff0c;python…

【性能设计篇】性能设计-缓存

前言 在分布式系统中&#xff0c;最耗费性能的地方就是数据库&#xff0c;而对于数据库的操作基本上就是添加&#xff0c;修改&#xff0c;删除和查询&#xff0c;对于前3者来说&#xff0c;基本上不会出现性能瓶颈。最耗费性能的地方就是查询了&#xff0c;对于查询有join、w…

Kafka相关知识

一、基本概念及流程 Broker:kafka集群中的实例Topic:队列的主题,逻辑概念;Partition:Topic分区,物理概念,同意parttion内消息有序;Producer & Consumer:生产消息的客户端 & 消费消息的客户端,kafka认为是服务器。将每个Topic划分为多个分区Partition,每个分…

Vim (NeoVim) 配置

Vim 基础 模式 o 代表的是open a new line i 代表的是insert a 代表的是append Visual [Character] 视觉模式&#xff1a;用于选择单个字符&#xff08;v小写’v’&#xff09;视觉线模式&#xff1a;用于一次选择整条线&#xff08;V大写“V”&#xff09;视觉块模式&#…

深度学习数据集—动物数据集大合集(二)

近期又整理了一批各类动物数据集&#xff0c;分享给大家。废话不多说&#xff0c;直接上干货&#xff01;&#xff01; 1、151种动物图片数据集共6271张&#xff0c;图片大小&#xff1a;224x224 jpg ​ ​ 下载地址&#xff1a;151种动物图片数据集 2、9种海洋生物&#xff0…

C++学习之字符常量、字符串常量和符号常量的区别

字符常量 字符常量就是把一个字符用单引号括起来。 注&#xff1a; 字符常量只能包含一个字符&#xff0c;如’AB’是不合法的字符常量区分大小写字母单引号“ ’ ”是定界符&#xff0c;而不属于字符常量的一部分 字符串常量 字符串常量时用双引号括起来的字符序列。 举例…

kill 命令信号详解

信号 列出所有信号 $ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18…

【数据结构】交换排序(详细)

交换排序 1. 冒泡排序2. 快速排序2.1霍尔版本2.2 挖坑法2.3 前后指针法&#xff08;最优&#xff09;2.4 小区间优化2.5 非递归快排 1. 冒泡排序 思想 排升序&#xff1a;每趟将前后两元素进行比较&#xff0c;按照“前小后大”进行交换&#xff0c;将最大的元素放在最后。 排…

Solr(3):Solr的名词解释及配置文件说明

1 名称解释 1.1 索引库 我们导入数据&#xff0c;solr 会被它以某种格式保存在索引库里面&#xff01; 可以看出刚安装的现在没有任何索引库 1.2 索引分词 Solr在导入数据库时&#xff0c;会对某些语句进行分词 1.3 搜索分词 Solr在搜索数据库时&#xff0c;会对某些语句进…

PyQt5桌面应用开发(10):界面布局基本支持

本文目录 PyQt5桌面应用系列布局利器游戏总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2&#xff09;&#xff1a;事件循环 PyQt5桌面应用开发&#xff08;3&#xff09;&#xff1a;并行设计 PyQt5桌…

星火认知大模型发布,科大讯飞入场科技巨头AI大战?

自从ChatGPT横空出世&#xff0c;一个更美好的世界开始向我们招手。为了推开新时代的大门&#xff0c;几乎所有人工智能厂商都投入了最大的热情逐浪AIGC。 5月6日&#xff0c;科大讯飞召开了“讯飞星火认知大模型”成果发布会。发布会现场&#xff0c;科大讯飞董事长刘庆峰展示…

Hadoop[3.3.x]-1本地环境搭建

环境&#xff1a;Mac Hadoop版本&#xff1a;Apache Hadoop 3.3.4 由于hadoop依赖java环境&#xff0c;所以需要事先安装好java。 Hadoop下载 进入官网进行下载Apache Hadoop 下载后解压到自己的规划的目录。 环境文件配置 Hadoop相关配置文件都在目录的../hadoop-3.3.4/et…

Vulkan 总结

一、Vulkan 对象简介 1、VKInstance 这个对象是我们 Vulkan api 的一个对象&#xff0c;用于通过 Instance 我们与 Vulkan 底层进行交互。 2、VkPhysicalDevice 对应我们当前设备&#xff08;PC、手机&#xff09;的一个显卡硬件&#xff08;GPU &#xff09;&#xff0c;有的…

如何导出cloudflare warp内部存的私钥和token

结论&#xff1a;管理员身份运行 mimikatz&#xff1a;https://github.com/gentilkiwi/mimikatz/releases/tag/2.2.0-20220919 然后输入&#xff1a; privilege::debug &#xff08;提升权限到&#xff1a;NT-AUTHORITY\SYSTEM&#xff09;以及sekurlsa::credman 就能看到&…

Java中的反射(通过反射获取类的结构、invoke方法、获取注解)

文章目录 1. 创建运行时类的对象2. 获取运行时类的完整结构2.1 相关API2.2 获取所有的属性及相关细节2.3 获取所有的方法及相关细节2.4 获取其他结构(构造器、父类、接口、包、注解等)2.5 获取泛型父类信息2.6 获取内部类或外部类信息2.7 总 结 3. 调用运行时类的指定结构3.1 调…

HDOJ 1022 Train Problem Ⅰ 模拟栈操作

&#x1f351; OJ专栏 &#x1f351; HDOJ 1022 Train Problem Ⅰ 输入 3 123 321 3 123 312输出 Yes. in in in out out out FINISH No. FINISH&#x1f351; 思路 &#x1f364; 栈顶元素与目标元素不匹配就进栈&#xff0c;匹配就出栈 &#x1f364; 匹配完&#xff1a;y…