C++的面向对象学习(6):运算符的重载

文章目录

  • 前言:什么是运算符重载?针对自定义的类与对象类型。
  • 一、加号的运算符重载
    • 1.引入背景
    • 2.所以运算符重载的作用:
    • 3.实现对象间的相加代码:+号运算符重载
      • ①在类中实现加号运算符重载
      • ②设计全局函数实现加号运算符重载
      • ③改写函数,实现对象与数值之间的相加
  • 二、左移与右移的运算符重载
    • 1.引入背景
    • 2.成员函数实现左移运算符重载
      • ①全局函数实现左移重载
      • ②成员变量一般是私有的,无法让全局函数访问,怎么办呢?
  • 三、递增运算符++的重载
    • 1.引入背景
    • 2.对成员变量实现前置递增和后置递增
  • 四、赋值运算符=的重载
    • 1.引入背景
    • 2.代码实现
  • 五、关系运算符(>、<、==、!=)的重载
    • 1.引入背景
    • 2.代码实现
  • 六、函数调用运算符()的重载
    • 1.背景引入
    • 2.代码例子:


前言:什么是运算符重载?针对自定义的类与对象类型。

运算符重载是C++中一种强大的特性,它允许我们为自定义的类类型定义运算符的行为。通过运算符重载,我们可以使用自定义的类对象像使用内置类型一样进行运算。

以下是一些常见的运算符重载示例:

算术运算符重载:+、-、*、/等运算符可以被重载,使得两个对象可以进行相应的运算。

关系运算符重载:==、!=、<、>、<=、>=等运算符可以被重载,用于比较两个对象的关系。

赋值运算符重载:=运算符可以被重载,用于将一个对象的值赋给另一个对象。

下标运算符重载:[]运算符可以被重载,用于实现类似数组的下标访问操作。

函数调用运算符重载:()运算符可以被重载,使得对象可以像函数一样被调用。

输入输出运算符重载:<<和>>运算符可以被重载,用于实现对象的输入和输出。

一、加号的运算符重载

1.引入背景

在这里插入图片描述
在这里插入图片描述
如果我想实现两个对象相加后,对应的变量之和等于第三个对象的该变量,直接相加肯定是不行的,会报错。
如果用常规的:
在这里插入图片描述
可以到是可以,但是如果人很多,从p1、p2、p3、…p100,我们想求出其总和放到一个对象中去,或者涉及很多字符串型变量的拼接,根本不可能一一写出来。另外,如果想用for循环来做累加操作也不行,因为对象名没有所谓的序号,不能用i来代替每一个对象。所以这就体现出运算符重载的作用了。

2.所以运算符重载的作用:

让类的对象这一特殊的类型,也具有加减乘除、赋值、比较、数组化的能力。

3.实现对象间的相加代码:+号运算符重载

①在类中实现加号运算符重载

class person {
public:int age;int money;person operator+(const person& other) {person result;result.age = this->age + other.age;result.money = this->money + other.money;return result;}
};

(1)在类中重载加法运算符时,我们定义了一个名为operator+的成员函数。这个函数接受一个person对象的引用作为参数,表示要与当前对象相加的另一个对象。函数体内,创建了一个新的person对象result,用于存储相加的结果。然后将当前this指针指向的对象的年龄和另一个对象的年龄相加,并将结果赋值给result对象的年龄成员变量。
最后,返回result对象就实现了将两个person对象的年龄和钱相加,并将结果作为新的person对象返回。

(2)通过自己写成员函数,就实现了两个对象的各个属性相加后返回新的对象功能。

(3)operator+是什么?
就是一个函数名称,这是person类的成员函数。在主函数中,我们可以这样调用:

int main()
{person p1;p1.age = 15;p1.money = 1000;person p2;p2.age = 18;p2.money = 1500;//想实现第三个对象p3的年龄和钱是p1p2的加和person p3 = p1.operator+(p2);system("pause");
}

但是编译器很聪明,他看到operator+这个形式,便可以直接简化理解成:

//想实现第三个对象p3的年龄和钱是p1p2的加和person p3 = p1+p2;

在重载的加法运算符函数中,关键字 this 指向当前对象,也就是 p1。而参数 other 则指向传递进来的对象,也就是 p2。在函数内部,this 指向 p1,other 指向 p2。

②设计全局函数实现加号运算符重载

person operator+(person& p1, person& p2) {person res;res.age = p1.age + p2.age;res.money = p1.money + p2.money;return res;
}int main()
{person p1;p1.age = 15;p1.money = 1000;person p2;p2.age = 18;p2.money = 1500;//全局函数的加号重载调用person p4 = p1 + p2;system("pause");
}

③改写函数,实现对象与数值之间的相加

//实现一个对象与常数相加的重载
person operator+(person& p1, int num) {person val;val.age = p1.age + num;val.money = p1.money + num;return val;
}

二、左移与右移的运算符重载

1.引入背景

常规的左移运算符 << 和右移运算符 >> 是 C++ 中的位运算符,用于对流对象进行输入和输出操作。它们也可以被重载以实现自定义的输入和输出行为。

string myname="xiaoming";
cout<<"hello world"<<myname<<endl;
int val;
cin>>val;

现在我有个需求,对于一个类的对象:
在这里插入图片描述

person p1;
p1.age=18;
p1.money=5000;
cout<<p<<endl;

我想让cout可以直接输出p的所有成员属性,显然目前的语法规则是不允许的,我们只能单独一项一项的打印输出。
重载左移运算符 << 可以用于 自定义对象 的输出操作,使其能够以自定义的方式输出到流对象中。重载右移运算符 >> 则可以用于 自定义对象 的输入操作,使其能够以自定义的方式从流对象中读取数据。

2.成员函数实现左移运算符重载

①全局函数实现左移重载

在这里插入图片描述

如果把cout和对象p作为函数的两个传参的话,那首先得明确cout到底是个什么类型的变量?

cout 是 C++ 标准库中的一个对象,它是 std::ostream 类型的变量。std::ostream 是一个输出流类,用于将数据输出到不同的目标,比如控制台、文件等。
cout 对象是 std::ostream 类的一个实例,它定义了一系列的成员函数,如 operator<<,用于将不同类型的数据输出到流中。通过使用 << 运算符,我们可以将数据插入到 cout 流中,并将其输出到标准输出设备(通常是控制台)。

在这里插入图片描述
osteam是输出流类的一个对象,全局只有一个,用引用传值。

//实现一个对象与cout的左移运算符重载
ostream& operator<<(ostream& out, person& p) {out << p.age << endl;out << p.money << endl;return out;
}

out是类ostream的引用对象,把结果又引用返回给cout这个唯一的对象。

②成员变量一般是私有的,无法让全局函数访问,怎么办呢?

上一节说了,想让函数访问私有成员变量,有很多办法。
首先可以在类里面写函数接口,但是变量多起来就比较麻烦。

另外就是使用友元声明。可以直接用friend声明友元类或者友元全局函数,就可以直接访问私有变量了。而友元类的成员函数去访问另一个类的私有变量上次编译器总是报错,就不推荐了。

class person{
friend ostream& operator<<(ostream& out, person& p);
private:int a;int b;
public:person(int x,int y){a=x;b=y;}
}//实现一个对象与cout的左移运算符重载
ostream& operator<<(ostream& out, person& p) {out << p.age1 << endl;out << p.money1 << endl;return out;
}int main(){person p1(1,2);cout<<p1<<endl;
}

三、递增运算符++的重载

1.引入背景

实现:实例化一个对象后,可以直接对该对象进行前置++和后置++的操作。

person p1;
p1++;
++p1;

2.对成员变量实现前置递增和后置递增

class Counter {
public:Counter() : count(0) {}// 前置递增运算符Counter& operator++() {++count;return *this;}// 后置递增运算符Counter operator++(int) {Counter temp = *this;++count;return temp;}private:int count;
};

前置递增运算符(++)重载函数返回一个引用,它将计数器的值加1,并返回自身的引用。这样,我们可以使用前置递增运算符来直接对计数器对象进行递增操作。

后置递增运算符(++)重载函数接受一个额外的int参数(通常不使用),用于区分前置递增和后置递增。它首先创建一个临时的Counter对象temp,将当前计数器的值赋给temp,然后将计数器的值加1,并返回temp对象。这样,我们可以使用后置递增运算符来对计数器对象进行递增操作,同时还可以获取递增前的值。
主程序里:

Counter counter;
++counter;  // 前置递增
int previousValue = counter++;  // 后置递增,并获取递增前的值

四、赋值运算符=的重载

1.引入背景

实现:实例化两个对象后,可以直接让第二个对象赋值给第一个对象。

person p1;
person p2;
p2=p1;

2.代码实现

	//赋值运算符重载person& operator=(const person& other) {if (this != &other) {count = other.count;}return *this;}

person& operator=(const person& other): 这是赋值运算符重载函数的声明,它指定了函数的返回类型为person&,表示返回一个对当前对象的引用。参数other是一个常量引用,表示要赋值的另一个person对象。

if (this != &other): 这是一个条件判断语句,用于检查是否是自我赋值。this是指向当前对象的指针,&other是指向另一个对象的指针。如果它们不相等,说明不是自我赋值,可以进行赋值操作。

count = other.count;: 这行代码将另一个对象other的count成员变量的值赋给当前对象的count成员变量。这是一个简单的赋值操作,用于复制对象的状态。

return this;: 这行代码返回对当前对象的引用,以支持链式赋值操作。通过返回this,可以允许连续多次赋值,例如p1 = p2 = p3;。

五、关系运算符(>、<、==、!=)的重载

1.引入背景

要实现对象的关系比较

person p1;
person p2;p1>p2;
p1==p2;
p1!=p2;

2.代码实现

class person {
public:// 构造函数和其他成员函数的实现person(int a):count(a){}bool operator>(const person& other) const {if(this->count > other.count){return true;}else return false;}bool operator<(const person& other) const {return count < other.count;}bool operator==(const person& other) const {return count == other.count;}bool operator!=(const person& other) const {return count != other.count;}private:int count;// 其他成员变量
};int main(){person p1(2);person p2(5);// 使用关系运算符进行比较
if (p1 > p2) {// p1的count大于p2的count
} else if (p1 < p2) {// p1的count小于p2的count
} else if (p1 == p2) {// p1的count等于p2的count
} else {// p1的count不等于p2的count
}
}

六、函数调用运算符()的重载

1.背景引入

函数调用运算符的重载常常用于创建仿函数(Functor)。仿函数是一种行为类似于函数的对象,可以像函数一样被调用。

2.代码例子:

下面是一个示例,展示了如何创建一个简单的仿函数:

class Adder {
public:int operator()(int x, int y) const {return x + y;}
};int main() {Adder add;int result = add(3, 4); // 调用仿函数// result 等于 7return 0;
}

在上述示例中,我们定义了一个名为Adder的类,并在其中重载了函数调用运算符()。在重载函数中,我们将两个整数相加,并返回结果。

在main函数中,我们创建了一个Adder对象add,并使用add(3, 4)的语法来调用仿函数。这将返回3 + 4 = 7的结果,并将其存储在result变量中。

仿函数可以像函数一样接受参数,并返回结果。它们可以用于算法函数、STL容器和其他需要函数对象的场景。

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

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

相关文章

JuiceSSH结合内网穿透实现公网远程访问本地Linux虚拟机

文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …

释放云服务器ECS实例

目录 云服务器ECS 释放设置 云服务器ECS 当你不想继续使用云服务器ECS&#xff0c;可以直接释放这个实例&#xff0c;但是需要注意的是实例释放后数据无法恢复&#xff0c;免费领取的实例也不能再次领取&#xff0c;一定谨慎进行ECS实例的释放&#xff0c;具体释放限制和建议…

C++ 比 C语言的新增的特性 1

1. C是C的增强 1.1 C是静态类型的语言&#xff0c;具有严格的数据类型检查 1.1.1 c 因为const修饰的变量不允许修改&#xff0c;但是只给了警告&#xff0c;不严谨 const int a10;a20; //报错int *p&a;*p20;//a的值&#xff1f; test1.c:6:9: warning: initialization dis…

【网络安全 | MD5截断比较】PHP、Python脚本利用

前言 在解题中&#xff0c;当遇到类似 substr(md5(a),-6,6) 7788这样的MD5截断比较的题目时&#xff0c;只有求出a的值才能进行接下来的操作。 一个一个去猜是不可能的&#xff0c;通常使用脚本解决&#xff0c;文末给出实战案例。 PHP循环脚本 <?phpfor($i1;$i<9…

【网络奇遇记】揭秘计算机网络的性能指标:速率|带宽|吞吐量|时延

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 速率1.1 数据量1.2 速率 二. 带宽三. 吞吐量四. 时延4.1 发送时延4.2 传播时延…

SpringMVC之跨域请求

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 SpringMVC之跨域请求 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是同源策略…

【C# 技术】 C# 常用排序方式——常规数据排序

C# 常用排序方式——常规数据排序 前言 在最近的项目中经常会对C#中的数据进行排序&#xff0c;对于基本数据类型&#xff0c;其排序方式比较简单&#xff0c;只需要调用内置算法即可实现&#xff0c;但对于自定义数据类型以及自定义排序规则的情况实现起来就比较麻烦&#…

这款APP,在离线环境下也能查看倾斜模型、点云等数据

《四维轻云-离线版》APP是基于移动端开发的轻量化地理空间数据应用平台&#xff0c;实现了用户对空间数据场景的制作和应用。 目前&#xff0c;已涵盖的数据类型包括倾斜模型(.osgb)、激光点云(.las)、正射影像(dom)、数字高程模型(dem)、矢量数据(shp)、人工模型&#xff08;…

IntelliJ IDEA 2023.3 安装教程

引言 IntelliJ IDEA&#xff0c;通常简称为 IDEA&#xff0c;是由 JetBrains 开发的一款强大的集成开发环境&#xff0c;专为提升开发者的生产力而设计。它支持多种编程语言&#xff0c;包括 Java、Kotlin、Scala 和其他 JVM 语言&#xff0c;同时也为前端开发和移动应用开发提…

TCP:IP原理

TCP/IP 原理 TCP/IP 协议不是 TCP 和 IP 这两个协议的合称&#xff0c;而是指因特网整个 TCP/IP 协议族。从协议分层模型方面来讲&#xff0c;TCP/IP 由四个层次组成&#xff1a;网络接口层、网络层、传输层、应用层。 网络访问层(Network Access Layer) 网络访问层(Network …

千帆起航:探索百度智能云千帆AppBuilder在AI原生应用开发中的革新之路

千帆起航&#xff1a;探索百度千帆AppBuilder在AI原生应用开发中的革新之路 1.揭开帷幕&#xff0c;大模型第二次战役 自从 ChatGPT 横空出世后&#xff0c;一石激起千层浪&#xff0c;人工智能也正在从感知理解走向生成创造&#xff0c;这是一个关键里程碑。生成式大模型完成…

【K8S基础】-k8s的核心概念控制器和调度器

Kubernetes是一个开源的容器编排平台&#xff0c;旨在简化和自动化容器化应用程序的部署、扩展和管理。它提供了一个强大的基础设施来管理容器化应用程序的生命周期&#xff0c;并确保它们在整个集群中高效运行。 Kubernetes的核心概念包括集群、节点、Pod、控制器、调度器等。…

[机器人-3]:开源MIT Min cheetah机械狗设计(三):嵌入式硬件设计

目录 概述&#xff1a; 1、硬件组成 2、通信速率 3、通信协议 4、mbedOS 概述&#xff1a; 以1条腿进行设计&#xff0c;其它腿也一样&#xff1a; 腿部硬件组成 1、硬件组成 1&#xff09;UP board计算机板卡&#xff08;Linux OS&#xff09;&#xff1a; 腿部控制器…

SpringMVC核心处理流程梳理

1、处理流程图展示 当我拿出这张图&#xff0c;阁下又该如何应对呢&#xff1f;执行流程是不是一目了然了。 2、DispatcherServlet&#xff1a;中央处理器或者中央调度器 下图官方的解释应该最完善了。 3、SpringMVC三大核心组件 HandlerMapping 处理器映射器&#xff0c;…

持续集成交付CICD:Jira 发布流水线

目录 一、实验 1.环境 2.GitLab 查看项目 3.Jira 远程触发 Jenkins 实现合并 GitLab 分支 4.K8S master节点操作 5.Jira 发布流水线 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 主机架构版本IP备注master1K8S master节点1.20.6192.168.204.180 jenkins…

深度学习 Day21——J1ResNet-50算法实战与解析

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文章目录 前言一、我的环境二、代码实现与执行结果1.引入库2.设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;3.导入数据4.查…

word2003 open word2007+

Win 7 C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates 还是不行&#xff0c;重装office2003吧&#xff0c;再安装转换插件&#xff0c;但是再高版本好像没转换工具

PyTorch加载数据以及Tensorboard的使用

一、PyTorch加载数据初认识 Dataset:提供一种方式去获取数据及其label 如何获取每一个数据及其label 总共有多少的数据 Dataloader:为后面的网络提供不同的数据形式 数据集 在编译器中导入Dataset from torch.utils.data import Dataset 可以在jupyter中查看Dataset官方文档&…

[C/C++]数据结构: 链式二叉树的构建及遍历

一: &#x1f4ac;二叉树的概念 1.1:&#x1f6a9; 概念 二叉树是指树中节点的度不大于2的有序树,它是一种最简单且重要的树,二叉树的递归定义为:二叉树是一颗空树,或者是一颗由一个根节点和两颗互不相交的,分别称为跟的左孩子和右孩子树组成的非空树,其中左子树和右子树都是二…

【C++11特性篇】模板的新一力将:可变参数模板 [全解析]

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Linux》专…