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.hqwc.cn/news/427643.html

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

相关文章

基于Java SSM框架实现医院预约挂号系统项目【项目源码】计算机毕业设计

基于java的SSM框架实现医院预约挂号系统演示 JSP技术介绍 JSP技术本身是一种脚本语言&#xff0c;但它的功能是十分强大的&#xff0c;因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时&#xff0c;它可以使显示逻辑和内容分开&#xff0c;这就极大的方便了用户的需…

.git 文件夹结构解析

.git 文件夹结构解析 在这篇文章就让我们来看看这个 Git 仓库里的文件分别都是用来干什么的&#xff0c;以及在执行了相关的 Git 命令后这些文件会如何响应。 hooks&#xff08;钩&#xff09;&#xff1a;存放一些shell脚本info&#xff1a;存放仓库的一些信息logs&#xff…

JAVA文件操作IO流(一)

File 文件对象 文件 在计算机中&#xff0c;文件是非常重要的存储方式&#xff0c;JAVA的标准库java.io提供了File对象来操作文件和目录。要构建一个File对象&#xff0c;需要通过构建方法&#xff0c;传入该文件的本地物理路径。 例如&#xff1a; 获取文件对象的1.绝对路径…

51单片机8*8点阵屏

8*8点阵屏 8*8点阵屏是一种LED显示屏&#xff0c;它由8行和8列的LED灯组成。每个LED灯的开闭状态都可以独立控制&#xff0c;从而可以显示出数字、字母、符号、图形等信息。 8*8点阵屏的原理是通过行列扫描的方式&#xff0c;控制LED灯的亮灭&#xff0c;从而显示出所需的图案或…

USRP相关报错解决办法

文章目录 前言一、本地环境二、相关报错信息二、解决办法1、更换电脑操作系统2、升级最新版固件 前言 在进行 USRP 开发时遇到了一些报错&#xff0c;这里做个记录解决问题的方法。 一、本地环境 电脑操作系统&#xff1a;Windows11MATLAB 版本&#xff1a;MATLAB 2021aUSRP …

C#,生成图片的指定尺寸缩略图的源代码

编程的时候经常用到图像的缩略图。 本文发布一个用于生成指定尺寸的缩略图的简单方法。 1 文本格式 private void button1_Click(object sender, EventArgs e) { CreateThumbnail("demo.jpg", "demo_thumb.jpg", 128, 128); } private void CreateTh…

【Web前端开发基础】CSS3之Web字体、字体图标、平面转换、渐变

CSS3之Web字体、字体图标、平面转换、渐变 目录 CSS3之Web字体、字体图标、平面转换、渐变一、Web字体1.1 Web字体概述1.2 字体文件1.3 font-face 规则 二、字体图标2.1 字体图标2.2 字体图标的优点2.3 图标库2.4 下载字体包2.5 字体图标的使用步骤2.6 字体图标使用注意点2.7 上…

Poe聊天机器人平台吸引新用户可获得最高50美元的收入

Poe聊天机器人平台正加大对创作者的奖励力度&#xff0c;机器人创建者每吸引一个新订阅者&#xff0c;最高可获得50美元&#xff08;约等于358.465人民币&#xff09;的收入。在GPTs商店上传过自定义GPT的朋友可以将自己的机器人复刻到Poe上&#xff0c;看看能不能拿到一些零食…

【Py/Java/C++三种语言详解】LeetCode每日一题240122【贪心】LeetCode670、最大交换

文章目录 题目链接题目描述解题思路为什么是贪心一个带图的例子 代码pythonjavacpp时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目链接 LeetCode670、最大交换 题目描述 给定一个非负整数数组 nums 和一个整数 k &#xff0c;你需要将这个数组分成 k 个非空的连…

vue3使用AntV G6 (图可视化引擎)历程[二]

上期回顾:历程[一]描述了基本的树状图的绘制,默认节点类型defaultNode中的type是circle,下面这篇描述的是节点抽离自定义节点并做数据静态渲染。 官网地址:https://g6-next.antv.antgroup.com/manual/introduction 一、案例效果 二、自定义节点渲染 1. 主要通过G6.register…

aop介绍

AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向方面编程&#xff09;&#xff0c;可以说是OOP&#xff08;Object-Oriented Programing&#xff0c;面向对象编程&#xff09;的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构&#xff0c;用…

Spring Security架构

文章目录 过滤器回顾DelegatingFilterProxyFilterChainProxySecurityFilterChainSecurity Filters打印Security Filters将自定义过滤器添加到过滤器链 Handling Security ExceptionsSaving Requests Between AuthenticationRequestCachePrevent the Request From Being Saved R…