什么是操作符重载

article/2025/11/11 15:40:38
一、什么是操作符重载

操作符重载可以分为两部分:“操作符”和“重载”。说到重载想必都不陌生了吧,这是一种编译时多态,重载实际上可以分为函数重载和操作符重载。运算符重载和函数重载的不同之处在于操作符重载重载的一定是操作符。我们不妨先直观的看一下所谓的操作符重载:

复制代码
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int a = 2 , b = 3;
 8     float c = 2.1f , d = 1.2f;
 9     cout<<"a + b = "<<a+b<<endl;
10     cout<<"c + d = "<<c+d<<endl;
11     return 0;
12 }
复制代码

我们看到操作符“+”完成floatint两种类型的加法计算,这就是操作符重载了。这些内置类型的操作符重载已经实现过了,但是如果现在我们自己写过的类也要实现实现类似的加法运算,怎么办呢??比如现在现在有这样一个点类point,要实现两个点的相加,结果是横纵坐标都要相加,这时候就需要我们自己写一个操作符重载函数了。

View Code
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class point
 6 {    
 7     double x;
 8     double y;
 9 public:
10     double get_x()
11     {
12         return x;
13     }
14     double get_y()
15     {
16         return y;
17     }
18     point(double X = 0.0 , double Y = 0.0):x(X),y(Y){};
19     point operator +(point p);
20 };
21 //重载操作符“+”
22 point point::operator +(point p)
23 {
24     double x = this->x + p.x;
25     double y = this->y + p.y;
26     point tmp_p(x,y);
27     return tmp_p;
28 }
29 int main()
30 {
31     point p1(1.2,3.1);
32     point p2(1.1,3.2);
33     point p3 = p1+p2;
34     cout<<p3.get_x()<<" "<<p3.get_y()<<endl;
35     return 0;
36 }

 

二、实现操作符重载的两种方式

操作符重载的实现方式有两种,即通过“友元函数”或者“类成员函数”。

1.友元函数重载操作符的格式:

复制代码
1 class 类名
2 {
3     friend 返回类型 operator 操作符(形参表);
4 };
5 //类外定义格式:
6 返回类型 operator操作符(参数表)
7 {
8     //函数体
9 }
复制代码

2.类成员函数实现操作符重载的格式:

复制代码
 1 class 类名
 2 {
 3 public:
 4     返回类型 operator 操作符(形参表);
 5 };
 6 //类外定义格式
 7 返回类型 类名::operator 操作符(形参表)
 8 {
 9     //函数体
10 }
复制代码

这样说吧,还是不足以比较这两种实现方式的区别,我们分别用两种实现方式写point类的”+“和”-“的重载。代码如下:

View Code
 1 #include <iostream>
 2 
 3 using std::endl;
 4 using std::cout;
 5 
 6 class point
 7 {    
 8     double x;
 9     double y;
10 public:
11     double get_x()
12     {
13         return x;
14     }
15     double get_y()
16     {
17         return y;
18     }
19     point(double X = 0.0 , double Y = 0.0):x(X),y(Y){};
20     friend point operator -(point p1,point p2);
21     point operator +(point p);
22 };
23 //重载操作符“-”
24 point operator -(point p1,point p2)
25 {
26     double x = p1.get_x() - p2.get_x();
27     double y = p1.get_y() - p2.get_y();
28     point p3(x,y);
29     return p3;
30 }
31 //重载操作符“+”
32 point point::operator +(point p)
33 {
34     double x = this->x + p.x;
35     double y = this->y + p.y;
36     point tmp_p(x,y);
37     return tmp_p;
38 }
39 int main()
40 {
41     point p1(1.2,3.2);
42     point p2(1.1,3.1);
43     point p3 = p1+p2;
44     point p4 = operator-(p1,p2);
45     cout<<p3.get_x()<<" "<<p3.get_y()<<endl;
46     cout<<p4.get_x()<<" "<<p4.get_y()<<endl;
47     return 0;
48 }

这里不知道大家看到没有,利用友元函数重载二元操作符”-“时,形式参数是两个,而利用类成员函数时,形式参数却只有一个。这时因为类成员函数中存在this指针,这相当于一个参数,所以类成员实现操作符重载需要的形式参数比原来少一个,这比如:利用类成员函数实现一元操作符”-“,就不需要参数了。也正是因为这个原因,友元函数实现的操作符重载是有限制的,比如:[] ,(),->和 =不能利用友元函数实现运算符的重载。

在实际开发过程中,单目运算符建议重载为成员函数,而双目运算符建议重载为友元函数。通常下双目运算符重载为友元函数比重载为成员函数更方便,但是有时双目运算符必须重载为成员函数,例如赋值运算符=。还有如果需要修改对象内部的状态,一般可以选择利用类成员函数进行修改。

 

三、运算符重载的原则

这样一看,运算符重载还是蛮简单的嘛,实际上运算符重载也是要遵循一些原则的:

1.C++中只能对已有的C++运算符进行重载,不允许用户自己定义新的运算符。

2.C++中绝大部分的运算符可重载,除了成员访问运算符.,作用域运算符::,长度运算符sizeof以及条件运算符?:

3.运算符重载后不能改变运算符的操作对象(操作数)的个数。如:"+"是实现两个操作数的运算符,重载后仍然为双目运算符。

4.重载不能改变运算符原有的优先级和原有的结合性。

6.运算符重载不能全部是C++中预定义的基本数据,这样做的目的是为了防止用户修改用于基本类型数据的运算符性质。

 

四、为什么要进行运算符重载

关于运算符重载要遵循这么多原则,那

一、什么是操作符重载

 

操作符重载可以分为两部分:“操作符”和“重载”。说到重载想必都不陌生了吧,这是一种编译时多态,重载实际上可以分为函数重载和操作符重载。运算符重载和函数重载的不同之处在于操作符重载重载的一定是操作符。我们不妨先直观的看一下所谓的操作符重载:

 

复制代码
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int a = 2 , b = 3;
 8     float c = 2.1f , d = 1.2f;
 9     cout<<"a + b = "<<a+b<<endl;
10     cout<<"c + d = "<<c+d<<endl;
11     return 0;
12 }
复制代码

 

我们看到操作符“+”完成floatint两种类型的加法计算,这就是操作符重载了。这些内置类型的操作符重载已经实现过了,但是如果现在我们自己写过的类也要实现实现类似的加法运算,怎么办呢??比如现在现在有这样一个点类point,要实现两个点的相加,结果是横纵坐标都要相加,这时候就需要我们自己写一个操作符重载函数了。

 

View Code
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class point
 6 {    
 7     double x;
 8     double y;
 9 public:
10     double get_x()
11     {
12         return x;
13     }
14     double get_y()
15     {
16         return y;
17     }
18     point(double X = 0.0 , double Y = 0.0):x(X),y(Y){};
19     point operator +(point p);
20 };
21 //重载操作符“+”
22 point point::operator +(point p)
23 {
24     double x = this->x + p.x;
25     double y = this->y + p.y;
26     point tmp_p(x,y);
27     return tmp_p;
28 }
29 int main()
30 {
31     point p1(1.2,3.1);
32     point p2(1.1,3.2);
33     point p3 = p1+p2;
34     cout<<p3.get_x()<<" "<<p3.get_y()<<endl;
35     return 0;
36 }

 

 

 

二、实现操作符重载的两种方式

 

操作符重载的实现方式有两种,即通过“友元函数”或者“类成员函数”。

 

1.友元函数重载操作符的格式:

 

复制代码
1 class 类名
2 {
3     friend 返回类型 operator 操作符(形参表);
4 };
5 //类外定义格式:
6 返回类型 operator操作符(参数表)
7 {
8     //函数体
9 }
复制代码

 

2.类成员函数实现操作符重载的格式:

 

复制代码
 1 class 类名
 2 {
 3 public:
 4     返回类型 operator 操作符(形参表);
 5 };
 6 //类外定义格式
 7 返回类型 类名::operator 操作符(形参表)
 8 {
 9     //函数体
10 }
复制代码

 

这样说吧,还是不足以比较这两种实现方式的区别,我们分别用两种实现方式写point类的”+“和”-“的重载。代码如下:

 

View Code
 1 #include <iostream>
 2 
 3 using std::endl;
 4 using std::cout;
 5 
 6 class point
 7 {    
 8     double x;
 9     double y;
10 public:
11     double get_x()
12     {
13         return x;
14     }
15     double get_y()
16     {
17         return y;
18     }
19     point(double X = 0.0 , double Y = 0.0):x(X),y(Y){};
20     friend point operator -(point p1,point p2);
21     point operator +(point p);
22 };
23 //重载操作符“-”
24 point operator -(point p1,point p2)
25 {
26     double x = p1.get_x() - p2.get_x();
27     double y = p1.get_y() - p2.get_y();
28     point p3(x,y);
29     return p3;
30 }
31 //重载操作符“+”
32 point point::operator +(point p)
33 {
34     double x = this->x + p.x;
35     double y = this->y + p.y;
36     point tmp_p(x,y);
37     return tmp_p;
38 }
39 int main()
40 {
41     point p1(1.2,3.2);
42     point p2(1.1,3.1);
43     point p3 = p1+p2;
44     point p4 = operator-(p1,p2);
45     cout<<p3.get_x()<<" "<<p3.get_y()<<endl;
46     cout<<p4.get_x()<<" "<<p4.get_y()<<endl;
47     return 0;
48 }

 

这里不知道大家看到没有,利用友元函数重载二元操作符”-“时,形式参数是两个,而利用类成员函数时,形式参数却只有一个。这时因为类成员函数中存在this指针,这相当于一个参数,所以类成员实现操作符重载需要的形式参数比原来少一个,这比如:利用类成员函数实现一元操作符”-“,就不需要参数了。也正是因为这个原因,友元函数实现的操作符重载是有限制的,比如:[] ,(),->和 =不能利用友元函数实现运算符的重载。

 

在实际开发过程中,单目运算符建议重载为成员函数,而双目运算符建议重载为友元函数。通常下双目运算符重载为友元函数比重载为成员函数更方便,但是有时双目运算符必须重载为成员函数,例如赋值运算符=。还有如果需要修改对象内部的状态,一般可以选择利用类成员函数进行修改。

 

 

 

三、运算符重载的原则

 

这样一看,运算符重载还是蛮简单的嘛,实际上运算符重载也是要遵循一些原则的:

 

1.C++中只能对已有的C++运算符进行重载,不允许用户自己定义新的运算符。

 

2.C++中绝大部分的运算符可重载,除了成员访问运算符.,作用域运算符::,长度运算符sizeof以及条件运算符?:

 

3.运算符重载后不能改变运算符的操作对象(操作数)的个数。如:"+"是实现两个操作数的运算符,重载后仍然为双目运算符。

 

4.重载不能改变运算符原有的优先级和原有的结合性。

 

6.运算符重载不能全部是C++中预定义的基本数据,这样做的目的是为了防止用户修改用于基本类型数据的运算符性质。

 

 

 

四、为什么要进行运算符重载

 

关于运算符重载要遵循这么多原则,那么为什么还要进行运算符重载呢?为什么我不是写一个add()函数,代替operator +()呢??个人感觉C++中之所以要支持运算符的重载是为了与内置数据类型统一操作,比如:c = a + b 和 c = add(a,b),这看起来哪个更直观一点呢,显然是前者了。同时,我们希望操作我们自己定义的数据类型能像操作int和double这些内置数据类型一样方便。可能举这个加法的例子有点不好,现在加入重载的运算符是[],<<,^,|等呢?这时我们要用什么成员函数代替呢??代替之后又是一种什么效果呢?会一眼就看出来这个函数要干什么吗??

 

 

 

思考:C++中的++运算符是有两种的,这个我们怎么区别重载的是前自增还是后自增呢?

么为什么还要进行运算符重载呢?为什么我不是写一个add()函数,代替operator +()呢??个人感觉C++中之所以要支持运算符的重载是为了与内置数据类型统一操作,比如:c = a + b 和 c = add(a,b),这看起来哪个更直观一点呢,显然是前者了。同时,我们希望操作我们自己定义的数据类型能像操作int和double这些内置数据类型一样方便。可能举这个加法的例子有点不好,现在加入重载的运算符是[],<<,^,|等呢?这时我们要用什么成员函数代替呢??代替之后又是一种什么效果呢?会一眼就看出来这个函数要干什么吗??

 

思考:C++中的++运算符是有两种的,这个我们怎么区别重载的是前自增还是后自增呢?

(http://www.cnblogs.com/BeyondAnyTime/archive/2012/09/01/2666570.html)


http://chatgpt.dhexx.cn/article/SJoxFTE5.shtml

相关文章

前端知识点总结 Vue JS CSS

前端知识点 MVVM和MVC的区别什么是Vue生命周期钩子函数触发顺序 VueVue优点父子通信&#xff0c;兄弟通信指令V-if和V-show区别 Vue-loaderVue-key的作用v-modalVue data必须是函数的问题Vue slot Vue-router多个router-viewroute与router的区别导航守卫懒加载 ES6JavaScript同…

JavaScript进阶之手写Promise

前言 Promise异步编程的一种解决方案&#xff0c;比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现&#xff0c;ES6 将其写进了语言标准&#xff0c;统一了用法&#xff0c;原生提供了Promise对象。这里手写一次&#xff0c;希望能和大家一起彻底…

【数据库】MongoDB数据库详解

目录 一&#xff0c;数据库管理系统 1&#xff0c; 什么是数据库 2&#xff0c;什么是数据库管理系统 二&#xff0c; NoSQL 是什么 1&#xff0c;NoSQL 简介 2&#xff0c;NoSQL数据库 3&#xff0c;NoSQL 与 RDBMS 对比 三&#xff0c;MongoDB简介 1&#xff0c; MongoDB 是什…

面试06,[长亮科技]()(offer)、[荔枝]()FM(在确定部门和薪资)、[涂鸦智能]()(第一轮电话面半小时,待后续)、华资软件(HR面)、[广州速游]()(已挂)。至于公司怎么样不加以言论。

作者&#xff1a;Carson-Zhao 链接&#xff1a;https://ac.nowcoder.com/discuss/522002?type2&order0&pos16&page1&ncTraceId&channel-1&source_iddiscuss_tag_nctrack 来源&#xff1a;牛客网 总结一下这几天的面试吧&#xff01;从19号到现在23号…

SQL Foundation(1--13)

1&#xff1a;关系数据库的由来&#xff1a; IBM的工程师Dr E F codd 的关系型数据库模型发表于1970 论文名称&#xff1a; A relational Model of data for Large Shared Data Bank (这个在wiki 和google上可以搜到) SQL: Structured query language&#xff1a; oracle官方…

一、快速入门 MongoDB 数据库

文章目录 一、NoSQL 是什么1.1 NoSQL 简史1.2 NoSQL 的种类及其特性1.3 NoSQL 特点1.4 NoSQL 的优缺点1.5 NoSQL 与 SQL 数据库的比较 二、MongoDB 基础知识2.1 MongoDB 是什么2.2 MongoDB 的体系结构2.3 MongoDB 的特点2.4 MongoDB 键特性2.5 MongoDB 的核心服务和工具2.6 Mon…

数据库总结(考研复试和期末复习皆可用)

数据库总结 点击下载该文档 密码&#xff1a;cqoq 本人自制了简答题的速记卡片 地址&#xff0c;大家可以参考使用。[下载Markji App 使用] 第一章 绪论 1.1 数据库系统概述 数据库管理系统(DBMS)的功能: 数据定义功能数据组织、存储和管理数据库操纵功能数据库的事务和运行…

一步步教你轻松学KNN模型算法

一步步教你轻松学KNN模型算法 ( 白宁超 2018年7月24日08:52:16 ) 导读&#xff1a;机器学习算法中KNN属于比较简单的典型算法&#xff0c;既可以做聚类又可以做分类使用。本文通过一个模拟的实际案例进行讲解。整个流程包括&#xff1a;采集数据、数据格式化处理、数据分析、数…

Oracle实战详解

Oracle实战详解 1.oracle介绍 ORACLE数据库系统是美国ORACLE公司&#xff08;甲骨文&#xff09;提供的以分布式数据库为核心的一组软件产品&#xff0c;是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。比如SilverStream就是基于数据库的一种中间件。ORA…

数据库|SQL / MySQL的基本理论用法

本文从数据库MySQL的数据类型、关系模型、增删改查语句、管理MySQL、实用SQL语句、事务等方面进行介绍。 数据类型 对于一个关系表&#xff0c;除了定义每一列的名称外&#xff0c;还需要定义每一列的数据类型。关系数据库支持的标准数据类型包括数值、字符串、时间等&#xf…

KNN模型算法研究与案例分析

KNN模型算法研究与案例分析( 白宁超 2018年8月29日15:39:13 ) 导读&#xff1a;机器学习算法中KNN属于比较简单的典型算法&#xff0c;既可以做聚类又可以做分类使用。本文通过一个模拟的实际案例进行讲解。整个流程包括&#xff1a;采集数据、数据格式化处理、数据分析、数据归…

SQL总结

目录 简介 在Android中存储数据有时会用到数据库&#xff0c;Android给我们提供了 一系列的API来操作数据库&#xff0c;非常简单&#xff0c;我们只需要输入对应的SQL语句&#xff0c;甚至不懂SQL语句&#xff0c;只传入对应的参数即可使用。还有一些第三方库&#xff0c;如G…

Windows开机启动项设置详解

一、开机启动原理 Windows系统都有一个“启动”文件夹&#xff0c;把需要打开的程序的快捷方式或脚本放到“启动”文件夹里&#xff0c;就可以实现开机自启动。 启动”文件夹分为两种&#xff1a;“系统启动文件夹”和“用户启动文件夹”。 系统启动文件夹 Win10系统“启动”…

「C#」设置开机启动

自己写了个监控键盘按键的小程序。 在界面上实时显示按下的键&#xff0c;但是想实现程序的开机自启如何实现呢。 开机自启动一种是在windows的“C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup”家快捷方式。但是这种方法自测有时候不成功。…

centos7 设置开机启动项

高端的废话就是没有引言这种废话。 1.这里我已我的centos7为例输入&#xff1a; systemctl list-unit-files #查看开机启动表如图下&#xff1a; 最左边就是服务 &#xff0c;最右边就是状态 。如当你想要服务器开机启动firewalld&#xff08;防火墙&#xff09;输入 system…

计算机怎么管理自启,电脑如何设置开机启动项

大家都知道将程序添加到开机启动项进入系统就可以自动打开了&#xff0c;但是有些流氓软件会强制进入开机启动项&#xff0c;这就导致电脑开机速度变慢&#xff0c;内存占用过多&#xff0c;运行卡顿的问题。下面&#xff0c;我就教大家如何设置开机启动 现在几乎家家户户都配备…

电脑设置开机

我们知道电脑可以通过修改系统任务计划来实现定时关机的功能&#xff0c;那么&#xff0c;能不能让电脑实现自动开机的功能呢?答案是可以的&#xff0c;我们可以通过BIOS设置&#xff0c;指定电脑在某个时间点自动开机&#xff0c;接下来&#xff0c;小编来介绍一下如何通过BI…

nginx 设置开机自启动

一、下载 在windows下实现开机自启动需要一个开源项目Windows Service Wrapper 来实现。 我用的是这个版本。 下载下来&#xff0c;放在Nginx根目录下 下载下来&#xff0c;放在Nginx根目录下&#xff0c;名字改为start-nginx.exe&#xff0c;再新建一个txt文件&#xff0c…

Win11开机启动项怎么调整,Win11开机启动项怎么设置

Win11开机启动项怎么调整&#xff1f;Win11开机启动项怎么设置&#xff1f;现在很多应用或软件下载安装之后默认都是开机自启的&#xff0c;如果开机自启的软件多了的话难免会导致系统开机速度变慢。最近有使用win11系统的小伙伴就遇到了这个问题&#xff0c;有网友想了解怎么设…

windows设置开机启动程序

1.新建文件,填写路径 echo off cd F:\程序路径\ //后面填写3D所在的路径 F: //程序的个盘符 run.bat把这个文件填写完成后,改个名字,后缀改为bat,并把这个文件放在机房的程序目录下 2.设置开机计划任务 windows 7 在【开始】菜单中&#xff0c;输入【任务计划】&#xf…