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.rhkb.cn/news/244625.html

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

相关文章

【LeetCode: 36. 有效的数独 + 模拟】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Qt 多次绘图

使用Qt 的时候发现&#xff1a; 背景&#xff1a;自己定义一个类&#xff0c;把它和某个ui文件绑定。(类似 Qt creator 默认创建的工程&#xff09;问题&#xff1a;当鼠标在窗口内单击的时候会触发2次绘图。&#xff1f;难道不应该是一次吗&#xff1f; 于是开始了如下的测试…

设备通过GB28181注册到EasyCVR,平台看不到设备信息的排查方法汇总

智慧安防平台EasyCVR能在复杂的网络环境中&#xff08;专网、局域网、广域网、VPN、公网等&#xff09;将前端海量的设备进行统一集中接入与视频汇聚管理&#xff0c;平台支持设备通过4G、5G、WIFI、有线等方式进行视频流的接入与传输&#xff0c;支持的接入协议包括&#xff1…

【立创EDA-PCB设计基础完结】7.DRC设计规则检查+优化与丝印调整+打样与PCB生产进度跟踪

前言&#xff1a;本文为PCB设计基础的最后一讲&#xff0c;在本专栏中【立创EDA-PCB设计基础】前面已经将所有网络布线铺铜好了&#xff0c;接下来进行DRC设计规则检查优化与丝印调整打样与PCB生产进度跟踪 目录 1.DRC设计规则检查 2.优化与丝印调整 1.过孔连接优化 2.泪滴…

C# .NET读取Excel文件并将数据导出到DataTable、数据库及文本

Excel文件是存储表格数据的普遍格式&#xff0c;因此能够高效地读取和提取信息对于我们来说至关重要。C#语言借助.NET Framework和各种库的广泛功能&#xff0c;能够进行高效的数据操作。利用C#读取Excel文件并将数据写入数据库和DataTable&#xff0c;或者将数据用于其他目的&…

大数据开发之SparkSQL

第 1 章&#xff1a;spark sql概述 1.1 什么是spark sql 1、spark sql是spark用于结构化数据处理的spark模块 1&#xff09;半结构化数据&#xff08;日志数据&#xff09; 2&#xff09;结构化数据&#xff08;数据库数据&#xff09; 1.2 为什么要有sparksql hive on s…

Eyes Wide Shut? Exploring the Visual Shortcomings of Multimodal LLMs

大开眼界&#xff1f;探索多模态模型种视觉编码器的缺陷。 论文中指出&#xff0c;上面这些VQA问题&#xff0c;人类可以瞬间给出正确的答案&#xff0c;但是多模态给出的结果却是错误的。是哪个环节出了问题呢&#xff1f;视觉编码器的问题&#xff1f;大语言模型出现了幻觉&…

计算机网络基础概念解释

​ 1. 什么是网络 随着时代的发展&#xff0c;越来越需要计算机之间互相通信&#xff0c;共享软件和数据&#xff0c;即以多个计算机协同⼯作来完成业务&#xff0c;于是有了网络互连。 网络互连&#xff1a;将多台计算机连接在⼀起&#xff0c;完成数据共享。 数据共享本质是…

GPT科研应用与AI绘图及论文高效写作

详情点击链接&#xff1a;GPT科研应用与AI绘图及论文高效写作 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定制自己…

论文阅读笔记AI篇 —— Transformer模型理论+实战 (三)

论文阅读笔记AI篇 —— Transformer模型理论实战 &#xff08;三&#xff09; 第三遍阅读&#xff08;精读&#xff09;3.1 Attention和Self-Attention的区别&#xff1f;3.2 Transformer是如何进行堆叠的&#xff1f;3.3 如何理解Positional Encoding&#xff1f;3.x 文章涉及…

常用电子器件学习——MOS管

MOS管介绍 MOS&#xff0c;是MOSFET的缩写。MOSFET 金属-氧化物半导体场效应晶体管&#xff0c;简称金氧半场效晶体管&#xff08;Metal-Oxide-Semiconductor Field-Effect Transistor, MOSFET&#xff09;。 一般是金属(metal)—氧化物(oxide)—半导体(semiconductor)场效应晶…

【Unity学习笔记】Unity TestRunner使用

转载请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/details/135733479 作者&#xff1a;CSDN|Ringleader| 参考&#xff1a; Input testingGetting started with Unity Test FrameworkHowToRunUnityUnitTest如果对Unity的newInputSystem感…

qnx 上screen + egl + opengles 最简实例

文章目录 前言一、qnx 上的窗口系统——screen二、screen + egl + opengles 最简实例1.使用 addvariant 命令创建工程目录2. 添加源码文件3. common.mk 文件4. 编译与执行总结参考资料前言 本文主要介绍如何在QNX 系统上使用egl和opengles 控制GPU渲染一个三角形并显示到屏幕上…

【Flink-CDC】Flink CDC 介绍和原理概述

【Flink-CDC】Flink CDC 介绍和原理概述 1&#xff09;基于查询的 CDC 和基于日志的 CDC2&#xff09;Flink CDC3&#xff09;Flink CDC原理简述4&#xff09;基于 Flink SQL CDC 的数据同步方案实践4.1.案例 1 : Flink SQL CDC JDBC Connector4.2.案例 2 : CDC Streaming ETL…

threejs学习

重要概念&#xff08;场景、相机、渲染器&#xff09; 如下图所示&#xff0c;我们最终看到浏览器上生成的内容是通过虚拟场景和虚拟相机被渲染器渲染后的结果&#xff0c;下面首先介绍这三个概念&#xff0c;将贯穿所有简单复杂的threejs项目。 场景 Scene 虚拟的3D场景&a…

Linux中文件属性的获取(stat、chmod、Istat、fstat函数的使用)

修改文件权限 函数如下&#xff1a; chmod/fchmod函数用来修改文件的访问权限: #include <sys/stat.h> int chmod(const char *path, mode_t mode); int fchmod(int fd, mode_t mode); 成功时返回0&#xff1b;出错时返回EOF 注意&#xff1a;在vmware和windows共享的文…

【2024-01-22】某极验3流程分析-滑块验证码

声明&#xff1a;该专栏涉及的所有案例均为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;如有侵权&#xff0c;请私信联系本人删帖&#xff01; 文章目录 一、前言二、抓包流程分析1.刷新页面2.点击按钮进行验证…

PyTorch各种损失函数解析:深度学习模型优化的关键(2)

目录 详解pytorch中各种Loss functions mse_loss 用途 用法 使用技巧 注意事项 参数 数学理论公式 代码演示 margin_ranking_loss 用途 用法 使用技巧 注意事项 参数 数学理论公式 代码演示 multilabel_margin_loss 用途 用法 使用技巧 注意事项 参数 …

代码随想录第十五天| ● 层序遍历 10 ● 226.翻转二叉树 ● 101.对称二叉树

文章目录 层序遍历102. 二叉树的层序遍历思路一&#xff1a;递归思路二&#xff1a;层序遍历-迭代-借助队列 107. 二叉树的层序遍历 II思路&#xff1a;层序遍历后翻转数组result即可 199.二叉树的右视图思路&#xff1a;通过list数组储存每一层末尾值 637.二叉树的层平均值思路…

class_10:this关键字

this关键字是指向调用对象的指针 #include <iostream> #include <iostream> using namespace std;class Car{ public://成员数据string brand; //品牌int year; //年限//构造函数名与类名相同Car(string brand,int year){cout<<"构造函数中&#…