c++:类和对象(5),运算符重载

目录

运算符重载概念:

+运算符重载

    1.成员函数重载+号 

2.全局函数重载+号

打印结果:

<<运算符重载

 递增运算符重载

简单例子

输出结果为:

 赋值运算符重载

如何重载

输出结果为:

什么时候重载 

 关系运算符重载

简单例子:

输出结果如下:

函数调用运算符重载 

简单例子

输出结果为:


运算符重载概念:

对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的类型数据

+运算符重载

    1.成员函数重载+号 

#include<iostream>
using namespace std;class person 
{
public:// 1. 成员函数重载加号运算符// 这里重载了加号运算符,使得两个person对象相加时,可直接通过加号进行操作person operator+(person& p){person temp;temp.m_a = this->m_a + p.m_a; // 对m_a进行相加操作temp.m_b = this->m_b + p.m_b; // 对m_b进行相加操作return temp; // 返回相加后的结果}int m_a;int m_b;};void test01()
{person p1;p1.m_a = 10;p1.m_b = 20;person p2;p2.m_a = 10;p2.m_b = 20;person p3 = p1 + p2;  // 将p1和p2相加的结果赋值给p3cout << p3.m_a << endl; // 输出p3的m_a值cout << p3.m_b << endl; // 输出p3的m_b值
}int main()
{test01(); // 调用test01函数进行测试system("pause"); // 暂停系统, Windows下使用return 0;
}

以上代码定义了一个person类,并重载了+运算符,使得两个person对象可以通过+进行相加操作。测试时创建了两个person对象p1p2,将它们相加的结果赋值给p3,然后输出p3的成员变量m_am_b的值。

2.全局函数重载+号

#include <iostream>
using namespace std;class MyNumber 
{
private:int value;public:MyNumber(int val) : value(val) {}int getValue() const { return value; }// 友元函数,全局函数重载加号运算符friend MyNumber operator+(const MyNumber& num1, const MyNumber& num2);
};// 全局函数重载加号运算符
MyNumber operator+(const MyNumber& num1, const MyNumber& num2) 
{int sum = num1.value + num2.value;return MyNumber(sum);
}int main() 
{MyNumber num1(5);MyNumber num2(7);MyNumber sum = num1 + num2; // 使用重载的加号运算符进行相加操作cout << "num1 = " << num1.getValue() << endl;cout << "num2 = " << num2.getValue() << endl;cout << "sum = " << sum.getValue() << endl;return 0;
}

打印结果:

在上述示例代码中,定义了一个名为MyNumber的类,其中包含一个私有成员变量value和构造函数。

为了使全局函数能够访问MyNumber类的私有成员,我们将该全局函数声明为MyNumber类的友元函数。在这个友元函数operator+中,我们重载了加号运算符,实现了两个MyNumber对象相加操作,并返回一个新的MyNumber对象作为结果。

main函数中,我们创建了两个MyNumber对象num1num2,然后使用重载的加号运算符将它们相加,将结果赋值给sum。最后,通过getValue成员函数分别输出num1num2sum的值。

总结:对于内置的数据类型的表达式的运算符是不可能改变的


<<运算符重载

#include <iostream>
using namespace std;class Point 
{
private:int x, y;public:Point(int a = 0, int b = 0) : x(a), y(b) {}int getX() const { return x; }int getY() const { return y; }// 友元函数,全局函数重载输出运算符friend ostream& operator<<(ostream& os, const Point& p);
};// 全局函数重载输出运算符
ostream& operator<<(ostream& os, const Point& p) 
{os << "(" << p.x << ", " << p.y << ")";return os;
}int main() 
{Point p(3, 5);cout << "The coordinates of p: " << p << endl;return 0;
}

输出结果为:

The coordinates of p: (3, 5)

在上述示例代码中,定义了一个名为Point的类,其中包含了两个私有成员变量xy,以及构造函数和获取成员变量的成员函数。

为了实现以自定义的方式输出Point类对象,我们重载了输出运算符<<。全局函数operator<<接受一个ostream对象os和一个Point对象p作为参数。在函数体中,我们使用os对象来输出p的坐标信息。

main函数中,我们创建了一个Point对象p,然后使用重载的输出运算符将p输出到标准输出流中。输出的结果将会是形如(3, 5)的坐标信息。


 递增运算符重载

简单例子

#include <iostream>
using namespace std;class MyNumber 
{
private:int value;public:MyNumber(int val) : value(val) {}int getValue() const {return value;}// 重载前置递增运算符MyNumber& operator++() {value++;return *this;}// 重载后置递增运算符MyNumber operator++(int) {MyNumber temp(value);value++;return temp;}
};int main() 
{MyNumber num(5);cout << "原始值:" << num.getValue() << endl;MyNumber preIncrement = ++num; // 前置递增运算符cout << "前置递增后的值:" << num.getValue() << endl;cout << "前置递增值:" << preIncrement.getValue() << endl;MyNumber postIncrement = num++; // 后置递增运算符cout << "后置递增后的值:" << num.getValue() << endl;cout << "后置递增值:" << postIncrement.getValue() << endl;return 0;
}

在上述示例代码中,定义了一个名为MyNumber的类,其中包含一个私有成员变量value和构造函数。

MyNumber类中,我们重载了前置递增运算符(++num)和后置递增运算符(num++)。前置递增运算符函数返回一个引用,先将value成员变量加1,然后返回递增后的对象。后置递增运算符函数接受一个额外的整型参数(通常为0),用于区分前置和后置递增运算符,创建一个临时对象保存递增前的值,然后将value成员变量加1,并返回临时对象。

注意:区别前置加加和后置加加的返回类型,看是否错误的进行了重载函数。

main函数中,我们创建了一个MyNumber对象num,然后进行前置递增运算和后置递增运算。我们将递增后的num对象的值以及返回的递增前的对象的值进行输出。

输出结果为:

原始值:5
前置递增后的值:6
前置递增值:6
后置递增后的值:7
后置递增值:6

总结:前置++返回引用,后置++返回值, 还要加参数,区别重置函数。


 赋值运算符重载

如何重载

#include <iostream>
using namespace std;class MyClass 
{
private:int value;
public:MyClass(int val) : value(val) {}int getValue() const {return value;}// 赋值运算符重载MyClass& operator=(const MyClass& other) {if (this != &other) { // 检查自我赋值value = other.value;}return *this;}
};int main() 
{MyClass obj1(5);MyClass obj2(10);cout << "obj1的初始值: " << obj1.getValue() << endl;cout << "obj2的初始值: " << obj2.getValue() << endl;obj1 = obj2; // 使用赋值运算符将obj2的值赋给obj1cout << "赋值后,obj1的值: " << obj1.getValue() << endl;return 0;
}

在上述示例代码中,我们在MyClass类中重载了赋值运算符(operator=)。该函数接收一个常量引用参数 other,表示赋值运算符右侧的对象。

在重载函数中,我们首先进行自我赋值检查,以避免在赋值时发生错误。然后,将other对象的值赋给this指针所指向的对象的value成员变量。

main函数中,我们创建了两个MyClass对象 obj1 和 obj2。然后使用赋值运算符将 obj2 的值赋给了 obj1。最后输出 obj1 的值进行验证。

输出结果为:

obj1的初始值: 5
obj2的初始值: 10
赋值后,obj1的值: 10

什么时候重载 

  • 当类中含有指针成员变量时,需要深拷贝对象的内容而不只是复制指针的地址。通过重载赋值运算符,可以在对象赋值时自定义深拷贝的行为,确保指针所指的资源得到正确的复制和释放。

  • 当类中存在动态分配的资源,如文件句柄、网络连接等,需要在对象赋值时确保资源的正确释放和转移。

  • 当类中含有其他类对象作为成员变量时,通过重载赋值运算符,可以实现对成员对象的赋值操作。

  • 当使用类的对象进行赋值操作时,希望自定义赋值的行为,例如执行额外的检查、记录操作日志等。


 关系运算符重载

简单例子:

#include <iostream>
using namespace std;class Student 
{
private:int age;public:Student(int studentAge) : age(studentAge) {}// 重载等于运算符bool operator==(const Student& other) const {return (age == other.age);}// 重载小于运算符bool operator<(const Student& other) const {return (age < other.age);}int getAge() const {return age;}
};int main() 
{Student s1(20);Student s2(18);Student s3(20);cout << "s1的年龄: " << s1.getAge() << endl;cout << "s2的年龄: " << s2.getAge() << endl;cout << "s3的年龄: " << s3.getAge() << endl;// 使用重载的等于运算符if (s1 == s2) {cout << "s1 等于 s2" << endl;} else {cout << "s1 不等于 s2" << endl;}if (s1 == s3)  {cout << "s1 等于 s3" << endl;} else {cout << "s1 不等于 s3" << endl;}// 使用重载的小于运算符if (s1 < s2) {cout << "s1 小于 s2" << endl;} else {cout << "s1 不小于 s2" << endl;}if (s2 < s3) {cout << "s2 小于 s3" << endl;} else {cout << "s2 不小于 s3" << endl;}return 0;
}

在上述代码中,我们定义了一个 Student 类,其中包含一个私有的 age 成员变量和对应的访问器函数 getAge()

我们重载了等于运算符(==)和小于运算符(<)。在重载函数中,我们比较了两个 Student 对象之间的年龄。

在 main 函数中,我们创建了三个 Student 对象 s1s2 和 s3,并输出他们的年龄。

接下来,我们使用重载的等于运算符来比较 s1 和 s2,以及 s1 和 s3 的年龄是否相等,并输出结果。

然后,我们使用重载的小于运算符来比较 s1 和 s2,以及 s2 和 s3 的年龄大小,并输出结果。

输出结果如下:

s1的年龄: 20
s2的年龄: 18
s3的年龄: 20
s1 不等于 s2
s1 等于 s3
s1 不小于 s2
s2 小于 s3

函数调用运算符重载 

 由于重载后的使用的方式非常像函数的调用,因此称为仿函数。

简单例子

#include <iostream>
using namespace std;class MyFunction 
{
public:int operator()(int a, int b) {return a + b;}
};int main() 
{MyFunction myFunc;int result = myFunc(2, 3); // 调用重载的函数调用运算符cout << "调用结果: " << result << endl;return 0;
}

在上述代码中,我们定义了一个名为 MyFunction 的类,并重载了函数调用运算符 operator()。重载后的函数调用运算符将两个参数相加,并返回结果。

在 main 函数中,我们创建了 MyFunction 类的对象 myFunc。然后,我们将对象 myFunc 当作函数一样进行调用,传递两个参数,并将结果存储在 result 变量中。

输出结果为:

调用结果: 5

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

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

相关文章

springboot121编程训练系统设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的编程训练系统设计与实现 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四…

一文深度解读多模态大模型视频检索技术的实现与使用

当视频检索叠上大模型Buff。 万乐乐&#xff5c;技术作者 视频检索&#xff0c;俗称“找片儿”&#xff0c;即通过输入一段文本&#xff0c;找出最符合该文本描述的视频。 随着视频社会化趋势以及各类视频平台的快速兴起与发展&#xff0c;「视频检索」越来越成为用户和视频平…

SpringBoot 自定义Filter 提前返回 CORS 错误 处理前后端分离跨域配置无效问题解析

前言 浏览器有跨域限制&#xff0c;非同源策略 (协议、主机名或端口不同) 被视为跨域请求&#xff0c;解决跨域有跨域资源共享(CORS)、反向代理和 JSONP的方式。本篇通过 SpringBoot 的资源共享配置 (CORS) 来解决前后端分离项目的跨域&#xff0c;以及从原理上去解决跨域配置…

负载均衡流程

1、负载均衡流程图 2、触发负载均衡函数trigger_load_balance void trigger_load_balance(struct rq *rq) { /* Dont need to rebalance while attached to NULL domain */ if (unlikely(on_null_domain(rq)))//当前调度队列中的调度域是空的则返回 return; i…

【嵌入式学习】C++QT-Day1-C++基础

思维导图&&笔记 见我的博客&#xff1a;https://lingjun.life/wiki/EmbeddedNote/19Cpp 作业&#xff1a; 提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 要求使用C风格字符串完成 #include <iostream&…

[MRCTF2020]Ez_bypass1

代码审计&#xff0c;要求gg和id的MD5值相等而gg和id的值不等或类型不等 相同MD5值的不同字符串_md5相同的不同字符串-CSDN博客 不过这道题好像只能用数组 下一步是passwd不能是纯数字&#xff0c;但是下一个判断又要passwd等于1234567 这里通过passwd1234567a实现绕过 原…

3D点云数据的标定,从搭建环境到点云标定方法及过程,只要有一台Windows笔记本,让你学会点云标定

ptscloudpre: 点云标定准备&#xff1a; 说明&#xff1a; 如下介绍适用windows系统的电脑。apple笔记本同理&#xff0c;但是需要安装MAC版本的anaconda。网址&#xff1a;Free Download | Anaconda可下载对应MAC版本的Anaconda的安装包建议下载2022年或2021年的安装包安装。…

qml中访问控件内部的子项

如何访问Repeater类型内部的子项、Row等布局类型内部的子项以及ListView内部的子项等。。。 1、测试代码 import QtQuick 2.0 import QtQuick.Controls 2.12 import QtQuick.Window 2.12 import QtQuick.Layouts 1.3 import QtQml 2.12Window {id: windowobjectName: "m…

基于Python Django的大数据招聘数据分析系统,包括数据大屏和后台管理

基于Python Django的大数据招聘数据分析系统是一个综合利用大数据技术和数据可视化技术的招聘行业解决方案。该系统旨在帮助企业和招聘机构更好地理解和分析招聘市场的趋势和变化&#xff0c;从而提高招聘效率和质量。 首先&#xff0c;该系统提供了一个强大的后台管理功能&am…

Docker容器引擎(3)

目录 一.Docker 镜像的创建 1&#xff0e;基于现有镜像创建 2&#xff0e;基于本地模板创建 3.基于Dockerfile创建&#xff1a; Dockerfile 操作常用的指令&#xff1a; ADD 和 COPY 的区别&#xff1f; CMD 和 ENTRYPOINT 的区别&#xff1f; 容器启动命令的优先级 如…

前端vue集成echarts图形报表样例

文章目录 &#x1f412;个人主页&#x1f3c5;Vue项目常用组件模板仓库&#x1f4d6;前言&#xff1a;&#x1f415;1.在项目终端下载echarts依赖包&#x1f3e8;2.在main.js中导入echarts资源包并使用&#x1f380;3.在.vue文件中直接使用echarts&#xff0c;下面是一个样例&a…

[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

C语言-算法-线性dp

[USACO1.5] [IOI1994]数字三角形 Number Triangles 题目描述 观察下面的数字金字塔。 写一个程序来查找从最高点到底部任意处结束的路径&#xff0c;使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。 在上面的样例中&#xff0c;从 7 → 3 → 8 →…

yolov8上使用gpu教程

yolov8上使用gpu教程 安装Cuda和Cudnnyolov8上使用gpu 安装Cuda和Cudnn 1.查看支持的cuda版本&#xff0c;并去官网下载。 nvidia-smi2.网址&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive 3.安装细节 安装的前提基础是&#xff0c;有vs的C环境。我电脑有…

开始学习Vue2(组件的生命周期和数据共享)

一、组件的生命周期 1. 生命周期 & 生命周期函数 生命周期&#xff08;Life Cycle&#xff09;是指一个组件从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 生命周期函数&#xff1a;是由 vue 框架提供的内置函数&#xff0c;会伴随着 组件…

必知的量化交易基础

量化交易核心概念 量化思想 量化交易 量化交易是指以先进的数学模型代替人为的主观判断&#xff0c;利用计算机技术从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略&#xff0c;极大地减少了投资者情绪波动的影响&#xff0c;避免在市场极度狂热或悲观的…

对Git更深入了解与学习

对Git更深入了解与学习 0. 前言0.1 工作区与暂存区 1. git remote update origin2. git push origin --delete 分支名 删除远端分支3. git remote4. git fetch5. git status5.1 git status 直观理解5.2 暂存与暂存取消 &#xff08;git restore&#xff09;5.3 push之后 6. git…

SpringBootAdmin邮件通知

在上一篇中我们学习到了 Admin Service Clustering 分布式缓存配置 &#xff0c;这一篇我们来学习&#xff0c;客户端离线&#xff0c;出现故障的时候&#xff0c;我们这么能及时知道呢&#xff0c;发现邮件通知也许是最简单的方式了&#xff01; 邮件通知 邮件通知将作为使用…

Linux文本编辑器-vi/vim

一.vi/vim编辑器介绍 vi\vim是visual interface的简称, 是Linux中最经典的文本编辑器 同图形化界面中的 文本编辑器一样&#xff0c;vi是命令行下对文本文件进行编辑的绝佳选择。 vim 是 vi 的加强版本&#xff0c;兼容 vi 的所有指令&#xff0c;不仅能编辑文本&#xff0c;而…

哈希的基本概念(开散列和闭散列)(附代码)

哈希 哈希概念哈希冲突哈希函数常见的哈希函数 哈希冲突的解决闭散列开散列 哈希概念 传统的查找函数&#xff0c;搜索的效率取决于比较的次数。而hash算法&#xff1a;在理想情况下&#xff0c;可以不经过任何比较&#xff0c;一次就能得到要搜索的结果。 存储结构&#xff1…