当前位置: 首页 > news >正文

c++运算符重载

目录

运算符重载的基本概念

重载加号运算符(+)

类内实现

类外实现

运算符重载碰上友元函数

可重载和不可重载的运算符

可重载的运算符

不可重载的运算符

重载自加自减运算符(a++ ++a)

智能指针

重载等号运算符(=)

重载等于和不等运算符(==  !=)


运算符重载的基本概念

概念:

运算符重载与函数重载比较类似,相当于让一个运算符具有另外一种含义;

语法:

定义重载的运算符就像定义函数,只是该函数的名字是 operator@,这里的@代表了被重载的运算符。函数的参数中参数个数取决于两个因素。运算符是一元(一个参数)的还是二元(两个参数);运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)

重载加号运算符(+)

类内实现

#include <iostream>using namespace std;class person
{public:person(int age){this->age = age;}person operator+(person &p2)//{person p = (this->age+p2.age);return p;}int age;
};
void test01()
{person p1(10);person p2(20);person p3 = p1 + p2;cout << p3.age << endl;}
int main()
{test01();return 0;
}

类外实现

#include <iostream>using namespace std;class person
{public:person(int age){this->age = age;}int age;
};person operator+(person &p1,person &p2)//
{person p = (p1.age+p2.age);return p;
}void test01()
{person p1(10);person p2(20);person p3 = p1 + p2;cout << p3.age << endl;}
int main()
{test01();return 0;
}

运算符重载碰上友元函数

将左移运算符的重载函数声明为类的友元函数 就可以访问类的成员

#include <iostream>using namespace std;class person
{friend ostream & operator<<(ostream &cout,person &p);public:person(int age){this->age = age;}private:int age;
};ostream & operator<<(ostream &cout,person &p)
{cout << p.age;return cout;
}void test01()
{person p1(10);cout << p1 << endl;}
int main()
{test01();return 0;
}

可重载和不可重载的运算符

几乎c 中所有的运算符都可以重载,但运算符重载的使用时相当受限制的。特别是不能使用c 中当前没有意义的 运算符( 例如用 ** 求幂 ) 不能改变运算符优先级,不能改变运算符的参数个数。这样的限制有意义,否则,所有这些行为产生的运算符只会混淆而不是澄清寓语意。

可重载的运算符

不可重载的运算符

重载自加自减运算符(a++ ++a)

a++是先把a赋值到一个临时空间,再对a+1赋值给临时变量,等运算结束后才返回临时变量给a  (参与运算的是自加之前的值)

++a是先给a+1,直接对a赋值,不需要开辟临时空间(参与运算的是返回值的引用)

前置++返回的是引用

后置++返回的是对象

前置++调用void operator++()

后置++调用myint operator++(int) 后置++多了一个占位参数

#include <iostream>using namespace std;class myint
{public:myint &operator++(){this->num = this->num+1;return *this;}myint(int num){this->num = num;}myint operator++(int){myint tmp = *this;this->num = this->num+1;return tmp;}int num;
};ostream &operator<<(ostream& cout,myint &p)
{cout << p.num;return cout;
}#include <iostream>using namespace std;class myint
{public:myint &operator++(){this->num = this->num+1;return *this;}myint(int num){this->num = num;}myint operator++(int){myint tmp = *this;this->num = this->num+1;return tmp;}int num;
};ostream &operator<<(ostream& cout,myint &p)
{cout << p.num;return cout;
}void test01()
{myint p1(10);cout << p1 << endl;++p1;//调用operator++(p1)或者p1.operator()cout << ++p1 << endl;p1++;//cout << p1++ << end; //有些编译器会报错cout << p1 << endl;
}
int main()
{test01();return 0;
}

智能指针

我们经常new出一个对象,忘记释放,所以我们使用智能指针来维护

智能指针实质上是一个局部对象 这个局部对象维护了new出来的对象的地址,在局部对象的析构函数中,会帮忙释放new出来的对象

对于智能指针我们重载了->和* 让智能指针和普通指针一样使用

#include <iostream>using namespace std;class person
{public:person(int age ){this->age = age;}int age;
};class SmartPointer
{public:SmartPointer(person *p1){this->p = p1;}~SmartPointer(){delete p;cout << "释放了p" << endl;}person *p;
};void test01()
{//局部对象 在释放之前可以帮助释放pperson *p = new person(10);SmartPointer s1(p);cout << p->age <<endl;cout << 
}
int main()
{test01();return 0;
}

重载等号运算符(=)

编译器默认给每个类加上了四个函数

        默认的无参构造

        默认的拷贝构造

        析构函数

        operator=()

#include <iostream>
#include <string.h>using namespace std;class person
{public:person(){}person(int agel,char *namel){age = agel;name = new char[strlen(namel)+1];strcpy(name,namel);}person& operator=(person &p1){this->age = p1.age;this->name = new char[strlen(p1.name)+1];strcpy(this->name,p1.name);return *this;//返回p2 为什么不返回p1?可以连续赋值 p3 = p2 = p1}~person(){delete []name;}int age;char *name;
};void test01()
{person p1(10,(char *)"bob");person p2;p2 = p1;//p2.operator(person &p1)cout << p2.age << " " << p2.name <<endl;
}int main()
{test01();return 0;
}

重载等于和不等运算符(==  !=)

#include <iostream>
#include <string.h>using namespace std;class person
{public:person(){}bool operator==(person &p2){return this->age == p2.age && this->name == p2.name;}bool operator!=(person &p2){return this->age != p2.age || this->name != p2.name;}person(int age,string name){this->age = age;this->name = name;}int age;string name;
};void test01()
{person p1(10,"lucy");person p2(10,"bob");if(p1 == p2){cout << "p1 = p2" << endl;}if(p1 != p2){cout << "p1 != p2" << endl;}
}int main()
{test01();return 0;
}

函数调用符号()重载

一个类中重载了()的类,那么类的定义出来的对象可以像函数一样使用,本质是调用了operator()这个函数

#include <iostream>
#include <string.h>using namespace std;class Myadd
{public:int add(int a,int b){return a + b;}int operator()(int x,int y){return x + y;}
};void test01()
{Myadd p;cout << p.add(3,5) << endl;//p() 可以像函数一样调用的对象 函数对象cout << p(3,4) << endl;//p.operator()(3,4)cout << Myadd()(3,4) << endl;//定义一个匿名对象 Myadd().operator()(3,4)
}int main()
{test01();return 0;
}

尽量不要重载 || &&

不能重载 operator&& operator|| 的原因是,无法在这两种情况下实现内置操作符的完整语义。说得更具体一 些,内置版本版本特殊之处在于:内置版本的&& || 首先计算左边的表达式,如果这完全能够决定结果,就无需计算右边的表达式了-- 而且能够保证不需要。我们都已经习惯这种方便的特性了。 我们说操作符重载其实是另一种形式的函数调用而已,对于函数调用总是在函数执行之前对所有参数进行求值。
class Complex{
public :
        Complex( int flag)
        {
                this ->flag = flag;
        }
        Complex& operator +=(Complex& complex)
        {
                this ->flag = this ->flag + complex.flag;
                return * this ;
        }
        bool operator &&(Complex& complex)
        {
                return this ->flag && complex.flag;
        }
public :
        int flag;
};
int main(){
        Complex complex1( 0 ); //flag 0
        Complex complex2( 1 ); //flag 1
        //原来情况,应该从左往右运算,左边为假,则退出运算,结果为假
        //这边却是,先运算( complex1+complex2 ),导致, complex1 flag 变为         complex1+complex2 的值,complex1.a = 1
        // 1 && 1
        //complex1.operator&&(complex1.operator+=(complex2))
        if (complex1 && (complex1 += complex2))
        {
                //complex1.operator+=(complex2)
                cout << " !" << endl;
        }
        else {
                cout << " !" << endl;
        }
        return EXIT_SUCCESS;
}

符号重载总结

1.=, [], () -> 操作符只能通过成员函数进行重载
        例如 :p = 3 成员函数实现 p.operator=(3) 全局函数实现 operator(3,p) 如果把3写在左边 相当于 3 = p,将p赋值给3,但3是一个常量,常量不能作为左值
               
2.<< >> 只能通过全局函数配合友元函数进行重载
        例如:cout << p 因为要把cout放在操作符的左侧 不可能去修改标准库中的类 所以必须配合全局函数和友元函数进行重载
3.不要重载 && || 操作符,因为无法实现短路规则
        内置版本的&& || 首先计算左边的表达式
常规建议

相关文章:

c++运算符重载

目录 运算符重载的基本概念 重载加号运算符() 类内实现 类外实现 运算符重载碰上友元函数 可重载和不可重载的运算符 可重载的运算符 不可重载的运算符 重载自加自减运算符(a a) 智能指针 重载等号运算符&#xff08;&#xff09; 重载等于和不等运算符&#xff08…...

vue子组件向父组件传参的方式

在Vue中&#xff0c;子组件向父组件传递参数可以通过自定义事件和props属性来实现。下面是一些关键代码示例&#xff1a; 1. 使用自定义事件&#xff1a; 在子组件中&#xff0c;通过 $emit 方法触发一个自定义事件&#xff0c;并传递参数。 <template><button cli…...

代码随想录Day41| 343. 整数拆分 |

343. 整数拆分 class Solution { public:int integerBreak(int n) {vector<int> f(n1,0);f[2]1;for(int i3;i<n;i){for(int j1;j<i-1;j){f[i]max(f[i],max(f[i-j]*j,(i-j)*j));}}return f[n];} }; 96. 不同的二叉搜索树 class Solution { public:int numTrees(int…...

工厂模式-(简单工厂模式)

首先看一下设计模式的六大原则 设计模式的六大原则 1、开闭原则&#xff08;Open Close Principle&#xff09; 开闭原则就是说对扩展开放&#xff0c;对修改关闭。在程序需要进行拓展的时候&#xff0c;不能去修改原有的代码&#xff0c;实现一个热插拔的效果。所以一句话概…...

V8引擎是如何提升对象属性访问速度的?

JavaScript 中的对象是由一组组属性和值的集合&#xff0c;从 JavaScript 语言的角度来看&#xff0c;JavaScript 对象像一个字典&#xff0c;字符串作为键名&#xff0c;任意对象可以作为键值&#xff0c;可以通过键名读写键值。 然而在 V8 实现对象存储时&#xff0c;并没有…...

彩色相机工作原理——bayer格式理解

早期&#xff0c;图像传感器只能记录光的强弱&#xff0c;无法记录光的颜色&#xff0c;所以只能拍摄黑白照片。 1974年,拜尔提出了bayer阵列&#xff0c;发明了bayer格式图片。不同于高成本的三个图像传感器方案&#xff0c;拜尔提出只用一个图像传感器&#xff0c;在其前面放…...

IDEA中DEBUG技巧

Debug 介绍 Debug 设置 如上图标注 1 所示&#xff0c;表示设置 Debug 连接方式&#xff0c;默认是 Socket。Shared memory 是 Windows 特有的一个属性&#xff0c;一般在 Windows 系统下建议使用此设置&#xff0c;相对于 Socket 会快点。 ## Debug 常用快捷键 Win 快捷键M…...

人工智能训练师

人工智能训练师是一个较新的职业&#xff0c;2020年2月才被正式纳入国家职业分类目录。他们主要负责在人工智能产品使用过程中进行数据库管理、算法参数设置、人机交互设计、性能测试跟踪及其他辅助作业。 这个职业的背景源于AI公司从客户&#xff08;用户&#xff09;那里获取…...

【业务功能118】微服务-springcloud-springboot-Kubernetes集群-k8s集群-KubeSphere-OpenELB部署及应用

OpenELB部署及应用 一、OpenELB介绍 网址&#xff1a; openelb.io OpenELB 是一个开源的云原生负载均衡器实现&#xff0c;可以在基于裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。OpenELB 项目最初由 KubeSphere 社区发…...

Unity中Shader的模板测试

文章目录 前言什么是模板测试1、模板缓冲区2、模板缓冲区中存储的值3、模板测试是什么&#xff08;看完以下流程就能知道模板测试是什么&#xff09;模板测试就是在渲染&#xff0c;后渲染的物体前&#xff0c;与渲染前的模板缓冲区的值进行比较&#xff0c;选出符合条件的部分…...

Scala 高阶:Scala中的模式匹配

一、概述 Scala中的模式匹配&#xff08;case&#xff09;类似于Java中的switch...case&#xff0c;但是Scala的模式匹配功能更为强大。通过模式匹配&#xff0c;可以匹配更复杂的条件和数据结构&#xff0c;包括常量、类型、集合、元组等。而 Java 的 switch 语句只能用于匹配…...

分子生物学——分子机器

分子生物学——分子机器 文章目录 前言一、2016年度诺贝尔化学奖1.1. 介绍1.2. 什么是分子机器&#xff1f;1.3. 分子机器的意义 总结 前言 对于本次搜集分子生物学领域的一个诺贝尔奖的有关内容的作业 参考文献&#xff1a; https://www.cas.cn/zt/sszt/2016nobelprize/hxj/2…...

【简历优化】这套「实习、初级、中级」测试工程师求职简历模板,建议收藏。

历时2年&#xff0c;7000粉丝问答&#xff0c;帮助上百位“刚培训毕业”、“1~3年经验”的软件测试伙伴&#xff0c;成功入职&#xff01; 我将这些问题内容&#xff0c;会持续更新记录在 「软件测试」求职指南 专栏。 求职简历中的误区 对于简历应该具备哪些模块&#xff0c…...

vue中展示json数据的方法

推荐插件&#xff1a;bin-code-editor (gitee.io) bug-1:编辑器无法显示数据 原因&#xff1a;组件层级套用太深&#xff0c;导致无法显示数据 解决办法&#xff1a;减少在孙子及后代组件中使用插件。...

【SG滤波】三阶滤波、五阶滤波、七阶滤波(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

2013 ~【VUE+ ElementUI】——【上传、下载】进度计算

【VUE ElementUI】——【上传、下载】进度计算 上传&#xff1a;FormData方式上传&#xff0c;监听 onUploadProgress下载&#xff1a;blob文件流下载&#xff0c;监听 onDownloadProgress 上传&#xff1a;FormData方式上传&#xff0c;监听 onUploadProgress <el-upload:…...

android可见即可说实现方案

依赖于科大讯飞的asr识别能力&#xff0c;使用Android无障碍服务获取页面文本作为热词&#xff0c;注册到讯飞api&#xff0c;注册过后语音识别到热词的asr返回,利用WindowManager和无障碍的点击实现可见即可说功能 ## &#x20;无障碍服务获取需要注册的热词package com..mo…...

Pikachu Burte Force(暴力破解)

一、Burte Force&#xff08;暴力破解&#xff09;概述 ​ “暴力破解”是一攻击具手段&#xff0c;在web攻击中&#xff0c;一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认证接口进行尝试登录&#xff0c;直到得到正确的结果。 为了提高…...

SpringMVC之JSON返回及异常处理

目录 JSON处理 导入依赖 配置Spring-mvc.xml ResponseBody注解使用 测试 目录 JSON处理 导入依赖 配置Spring-mvc.xml ResponseBody注解使用 测试 Jackson 定义 用法 常用注解 统一异常处理 为什么要全局异常处理&#xff1f; 异常处理思路 SpringMVC异常分类 综…...

SkyWalking快速上手(六)——告警

文章目录 前言一、什么是SkyWalking的告警功能二、为什么要使用SkyWalking的告警功能1. 及时发现异常情况2. 提高故障处理效率3. 避免数据丢失和损坏4. 提升系统性能和稳定性 三、如何使用SkyWalking的告警功能1. 告警规则2. 告警通知3. 告警持续时间 四、注意事项1、合理设置告…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...