运算符重载(全局函数与类的成员函数分别解析)

news2025/1/12 10:12:17

运算符重载(全局函数)

在这里插入图片描述

  1. 比如说对于小于号和大于号,如果说是内置类型的话,可以直接进行比较,因为内置类型是祖师爷定义的,那祖师爷肯定知道比方说int类型怎么比,double类型怎么比,因为他肯定知道内置类型是怎么去进行比较,肯定就把相关的规则给他融合到指令当中,他是明牌。
  2. 但是如果说自定义类型的话,因为自定义类型是我们自己定义的,所以说可以五花八门,所以说祖师爷他不知道我们自己定义的各种各样的自定义类型之间该怎么去比较,所以说对于自定义类型而言,不能直接用小于号,大于号去进行比较。
  3. 因为自定义类型是我们自己定义的,***所以说对于自定义类型之间的比较的话,我们自己是知道的,***所以如果说我需要用小于号去比较一下两个自定义类型变量的话,那么我就需要把小于号这个运算符给他重载一下。
  4. 编译器如果碰到内置类型比较大小的话,因为他是知道内置类型是怎么去比较的,所以说就会直接转化为指令。然后对于自定义类型的话,它会转化为去调用这个函数operator>(打个比方)
  5. 运算符重载在实际上就是相当于我们希望对于自定义类型变量也可以像内置类型那样去使用运算符,因为这样子可读性就会更高
  6. 实际上在特定的场景下面,并不是所有的运算符都有意义,是否要重载运算符,取决于这个运算符对于这个类是否有意义。
  7. 然后由于自定义类型已经是相对来说一个比较复杂的类型了。要用运算符来进行比较的话,也不是很容易。所以这时候我们就自己去写一个函数来进行自我实现。也就是自己去修改这个运算符的实现逻辑(如果说这个运算符它的操作数是一个内置类型,那么就会直接转化为指令,如果说不是内置类型,那么就直接会去调用你自己写的这个运算符重载函数,所以说本质上就是转化成一个函数)
  8. 然后再实现这个运算符重载函数的时候,由于肯定会涉及到自定义类型实例化对象的传参,这时候结合之前的知识会发现肯定需要用引用与const为佳
  9. 在运算符重载的时候不能够去创造新的符号
  10. 对于那些乱七八糟的符号,就是不是运算符的符号是不能够进行运算符重载,然后有些符号它即使是作为运算符,但是也不能进行运算符重载,有5个:.* sizeof : : ?: .
  11. 代码样本:
#include <iostream>
#include <stdlib.h>
#include <stdbool.h>
using namespace std;
class Stu
{
public:
	//成员变量
	char* name;
	int age;
	double score;
	//成员函数
	//构造函数
	Stu(int size = 10)
	{
		name = (char*)malloc(sizeof(char) * size);
		if (name == nullptr)
		{
			perror("malloc failed");
			return;
		}
		age = 0;
		score = 0;
	}
	void input()
	{
		cout << "依次输入姓名,年龄与成绩:";
		cin >> name >> age >> score;
	}
	void output()
	{
		cout << name << " " << age << " " << score << endl;
	}
	~Stu()
	{
		free(name);
	}
};
void operator>(const Stu& x1, const Stu& x2)  //比较年龄
{
	if (x1.age > x2.age)
	{
		cout << "是的,"<< x1.name << "的年龄更大,为" << x1.age << "岁!" << endl;
	}
	else if (x1.age < x2.age)
	{
		cout << "不对" << x2.name << "的年龄更大,为" << x2.age << "岁!" << endl;
	}
	else
	{
		cout << "不完全对,两者年龄一样大" << endl;
	}
}
void operator<(const Stu& x1, const Stu& x2)  //比较年龄
{
	if (x1.score < x2.score)
	{
		cout << "是的," << x1.name << "的成绩更低,为" << x1.score << "分!" << endl;
	}
	else if (x1.score > x2.score)
	{
		cout << "不是," << x2.name << "的成绩更低,为" << x2.score << "分!" << endl;
	}
	else
	{
		cout << "不完全对,两者成绩一样" << endl;
	}
}
int main()
{
	Stu s1;
	Stu s2;
	s1.input();
	s2.input();
	cout << "s1>s2(我在比较年龄):";
	s1 > s2;
	cout << "s1<s2(我在比较成绩):";
	s1 < s2;
	return 0;
}

以后对于例化对象进行函数的传值调用,用于函数的传值返回,最好都去使用一下引用,并且如果可以的话,最好都加上const

运算符重载(类的成员函数)

  1. 但是到目前为止还存在着一个问题,由于在类的外面的话,不能够去访问那些私有或者受保护的成员变量,那如果说两个类的实例化对象需要去进行用运算符去比较的话,那么在那个具体实现逻辑的函数里面,必须需要去访问那些类的成员变量,需要与它打交道。那虽然在类外面无法进行访问,但是在类的里面的话是没有任何限制的,那就可以把那个运算符重载的函数给它放到类的里面去充当一个成员函数不就OK?但如果单独去这么做的话,你会发现还是编不过去

  2. 你想按道理来讲的话,如果说这个操作符它所能连接到的操作数有几个,那么在这个运算符重载函数当中的参数就应该有几个,比如说对于运算符重载函数operator>,那么这个函数它的参数肯定是两个。如果把运算符操作函数给它充当类的成员函数里面,这边就需要注意一个大坑,因为类的成员函数都隐藏着第一个参数,也就是this指针(类型* const this),这个隐藏的参数this指针其实就可以取代其中的某一个参数去进行对于某个实例化对象的成员访问

  3. this指针真想揭露:
    在这里插入图片描述

  4. 自定义类型的运算符重载在本质上就是在调用函数,但无非就是作为成员函数的时候,看起来参数好像少了一个的样子

  5. 代码样本:

#include <iostream>
#include <stdlib.h>
#include <stdbool.h>
using namespace std;
class Stu
{
public:
	//成员函数
	//构造函数
	Stu(int size = 10)
	{
		name = (char*)malloc(sizeof(char) * size);
		if (name == nullptr)
		{
			perror("malloc failed");
			return;
		}
		age = 0;
		score = 0;
	}
	void input()
	{
		cout << "依次输入姓名,年龄与成绩:";
		cin >> name >> age >> score;
	}
	void output()
	{
		cout << name << " " << age << " " << score << endl;
	}
	void operator>(const Stu& x2)  //比较年龄
	{
		if (age > x2.age)
		{
			cout << "是的," << name << "的年龄更大,为" << age << "岁!" << endl;
		}
		else if (age < x2.age)
		{
			cout << "不对" << x2.name << "的年龄更大,为" << x2.age << "岁!" << endl;
		}
		else
		{
			cout << "不完全对,两者年龄一样大" << endl;
		}
	}
	void operator<(const Stu& x2)  //比较年龄
	{
		if (score < x2.score)
		{
			cout << "是的," << name << "的成绩更低,为" << score << "分!" << endl;
		}
		else if (score > x2.score)
		{
			cout << "不是," << x2.name << "的成绩更低,为" << x2.score << "分!" << endl;
		}
		else
		{
			cout << "不完全对,两者成绩一样" << endl;
		}
	}
	~Stu()
	{
		free(name);
	}
private:
	char* name;
	int age;
	double score;
};
int main()
{
	Stu s1;
	Stu s2;
	s1.input();
	s2.input();
	cout << "s1>s2(我在比较年龄):";
	s1 > s2;
	cout << "s1<s2(我在比较成绩):";
	s1 < s2;
	return 0;
}
  1. 然后对于普通的运算符重载函数的话,他就可以写在类的外面,也就是可以写在全局域当中,但往往运算符重载函数会涉及到需要访问某个类的实例化对象的成员变量,而在全局那边有可能会受到访问限制符的限制,所以说针对特定类的某些运算符重载函数也一般是写在类的成员函数当中,这样在类里面的话就不会受到访问限定符的限制

补充与总结

  1. 对于那些比较运算符进行重载的时候,运算符之间本身就有一种互斥的关系,所以说这边就可以进行一些复用
  2. 于此同时在运算符重载的过程当中并没有规定操作数必须都是同一个类型,而仅仅只是规定了在操作数当中必须至少有一个是自定义类型,就是说不能全部都是内置类型,因为假设全部都是内置类型的话,那么就可以直接转化为指令了
  3. 在这里插入图片描述
  4. 总结图:
    在这里插入图片描述

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

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

相关文章

STL之search()算法

我们之前介绍的find()算法以及find_if()算法都帮助我们查找判断某一个value是否被包含在序列中&#xff0c;并返回它第一次出现时所处的位置&#xff0c;假如我想找到某一段满足条件的子区间&#xff0c;应该怎么做呢&#xff1f;C标准库又为我们提供了哪些算法呢&#xff1f; …

2023年4月《中国数据库行业分析报告》正式发布(含精彩内容概览)

为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况&#xff0c;从2022年4月起&#xff0c;墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》&#xff0c;持续传播数据技术知识、努力促进技术创新与行业生…

C语言课设项目-51单片机-红外通信

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一. 什么是红外线 二. 红外线系统的组成 三. 红外发射管 四. 红外遥控器发射 五. 红外线接收 六.数…

还能这么玩?清华给 ChatGPT 做逆向,发现了 ChatGPT 的进化轨迹!

作者 |小戏、Python 立足一个 ChatGPT&#xff0c;现在对大模型的研究简直是百花齐发百家争鸣&#xff0c;用 ChatGPT 做化学实验、给 ChatGPT 做心理测试、诱导 ChatGPT 越狱泄漏隐私、让几个 ChatGPT 形成一个小社会等等不胜枚举。 而最近&#xff0c;清华的研究团队又在大模…

深度学习01-tensorflow开发环境搭建

文章目录 简介运行硬件cuda和cuddntensorflow安装。安装Anaconda创建python环境安装tensorflow-gpupycharm配置配置conda环境配置juypternotebook 安装cuda安装cudnn 简介 TensorFlow是一种端到端开源机器学习平台&#xff0c;它提供了一个全面而灵活的生态系统&#xff0c;包…

unity进阶学习笔记:有限状态机

一般来说&#xff0c;每一个游戏物体会有多种状态&#xff0c;每一个状态会对应一个特定动画。如一个游戏角色可能有静止状态&#xff0c;移动状态&#xff0c;攻击状态。每一个状态里都有对应的动画。如果我们只是简单使用一个个if语句判断玩家进行哪个控制来切换动画会让程序…

一文打尽目标检测NMS(2): 效率提升篇

文章来自于&#xff1a;曲終人不散丶知乎&#xff0c; 连接&#xff1a;https://zhuanlan.zhihu.com/p/157900024&#xff0c; 本文仅用于学术分享&#xff0c;如有侵权&#xff0c;前联系后台做删文处理。 在笔者上一篇文章《一文打尽目标检测NMS——精度提升篇》中&#xff0…

博客系统后端设计(三) - 实现获取博客列表页功能

文章目录 实现获取博客列表页功能1. 约定前后端交互接口2. 实现后端代码3. 实现前端代码4. 测试代码5. 涉及到的两个 Bug 实现获取博客列表页功能 当前的博客列表上的数据都是写死的&#xff0c;符合逻辑的做法是&#xff0c;通过数据库读取数据后显示到页面上。 此处就需要打…

【Linux】2.2 环境基础开发工具使用——vim

文章目录 什么是 vimvim 的基本操作vim 指令集Normal mode 指令集插入模式复制粘贴撤销剪切光标移动删除 last line mode 指令集列出行号跳到文件中的某一行查找字符保存文件 vim 的配置 什么是 vim Linux editor —— vim ——多模式的编辑器每种模式有差异&#xff0c;模式之…

人工智能洗稿-免费自媒体洗稿工具

文字洗稿 文字洗稿是指通过修改、重组、删除、替换等手段对文本进行优化、清理和调整&#xff0c;以达到改善文章质量、增加独特性和提高可读性的目的。文字洗稿是自媒体行业的一个重要需求&#xff0c;尤其是在批量撰写文章或需要大量修改文本的情况下。文字洗稿分为自动洗稿…

记一次springboot项目漏洞挖掘

前言 前段时间的比赛将该cms作为了题目考察&#xff0c;这个cms的洞也被大佬们吃的差不多了&#xff0c;自己也就借此机会来浅浅测试下这个cms残余漏洞&#xff0c;并记录下这一整个流程&#xff0c;谨以此记给小白师傅们分享下思路&#xff0c;有错误的地方还望大佬们请以指正…

云办公时代,企业如何保护数据资产安全?

云办公是一种基于云计算技术的办公方式&#xff0c;它将传统的办公软件和数据存储方式转移到了云端服务器上。用户可以通过互联网访问各种办公应用程序和数据&#xff0c;实现远程协作、移动化办公和信息共享等功能。 常见的云办公应用包括文档处理、电子邮件、日历、在线会议、…

ABAP 锁对象

需求场景 最近收到用户反馈&#xff0c;发现同一个托运单生成了两个不同的服务订单以及根据同一个送货单生成了两个托运单&#xff0c;经过排查&#xff0c;发现原因都是由同样的问题导致的&#xff0c;多窗口或者多用户同时对一条数据操作&#xff0c;就会出现这种现象。这个…

Learning C++ No.19【搜索二叉树实战】

引言&#xff1a; 北京时间&#xff1a;2023/5/2/9:18&#xff0c;五一放假第四天&#xff0c;昨天本来想要发奋图强将该篇博客写完&#xff0c;但是摆烂了一天&#xff0c;导致已经好几天没有码字&#xff0c;敲代码了&#xff0c;此时难受的感觉涌上心头&#xff0c;但是摆烂…

DNF类游戏动作实现(C语言)

没有接触制作小游戏前&#xff0c;感觉做游戏很不可思议&#xff0c;游戏里的人物是怎么移动的&#xff0c;怎么攻击&#xff0c;释放技能。。。。。。现在逐渐了解到之后&#xff0c;发现2d游戏人物的动作更多是图片的拼接&#xff0c;动作是否精细&#xff0c;由这个动作的帧…

鲲鹏展翅 信安高飞 | 鲲鹏开发者峰会2023-麒麟信安技术论坛成功举办!

2023年5月6日-7日&#xff0c;以“创未来 享非凡”为主题的鲲鹏开发者峰会2023在东莞松山湖举办。鲲鹏产业生态繁荣&#xff0c;稳步发展&#xff0c;正在成为行业核心场景及科研领域首选&#xff0c;加速推动数字化转型。 作为鲲鹏生态重要合作伙伴&#xff0c;麒麟信安受邀举…

企企通:B2B商城四种“玩法”,一站式解决端到端全链路需求!

商城系统在电商零售领域中&#xff0c;一直是助力商家搭建商城的核心工具&#xff0c;随着电商行业的发展&#xff0c;各种新模式随即出现&#xff0c;与此同时也出现了各种各样的商城系统&#xff0c;而B2B商城是这其中最为常见的商城系统。 近年来&#xff0c;由于电子商务的…

相遇于此,相交链表的解题心得

本篇博客会讲解力扣“160. 相交链表”的解题思路&#xff0c;这是题目链接。 老规矩&#xff0c;先来审题。这道题的题干有点长&#xff0c;简而言之&#xff0c;就是判断2个链表是否相交&#xff0c;如果相交就返回第一个相交结点&#xff0c;不相交就返回NULL。看看题目原文…

【C++中可调用对象和function】

C中有如下几种可调用对象&#xff1a;函数、函数指针、lambda表达式、bind对象、仿函数。其中&#xff0c;lambda表达式和bind对象是C11标准中提出的(bind机制并不是新标准中首次提出&#xff0c;而是对旧版本中bind1st和bind2st的合并)。个人认为五种可调用对象中&#xff0c;…

FM33A048B LPUART

概述 LPUART 是一个低功耗UART 接口&#xff0c;其工作仅需32768Hz 时钟&#xff0c;可以支持到最高9600 波特率的数据接收。LPUART 功耗极低&#xff0c;可以在Sleep/DeepSleep 模式下工作。 特点&#xff1a; ⚫ 异步数据收发 ⚫ 标准UART帧格式 ◼ 1bit起始位 ◼ 7或8bit数据…