【C++面向对象】封装(下):探索C++运算符重载设计精髓


🔥个人主页 🔥
😈所属专栏😈
每文一诗 💪🏼
年年岁岁花相似,岁岁年年人不同 —— 唐/刘希夷《代悲白头翁》
译文:年年岁岁繁花依旧,岁岁年年看花之人却不相同
目录
C++运算符重载概念
C++运算符重载语法及作用
加减乘除运算符重载
赋值运算符重载
返回值作为引用以实现链式赋值
关系运算符重载
大于号运算符重载
相等运算符重载
全部代码
C++运算符重载概念
在 C++ 里,运算符重载属于多态的一种表现形式,它允许你为自定义的数据类型重新定义运算符的行为。
运算符重载其实就是对已有的运算符赋予新的功能,使它能够处理自定义类型的对象
C++运算符重载语法及作用
语法:返回类型 operator运算符(参数列表) {}
- 提高代码可读性:在处理自定义类型时,使用重载后的运算符能让代码更直观、自然。例如,对于自定义的复数类,你可以重载
+运算符,让两个复数相加的操作就像普通数字相加一样简单。 - 实现自定义类型的操作:借助运算符重载,你能为自定义类型实现像内置类型那样的操作。比如,对于自定义的矩阵类,你可以重载
+、-、*等运算符,实现矩阵的加减乘运算。 - 代码复用与一致性:运算符重载可以复用已有的运算符,使代码更具一致性。对于熟悉内置运算符的开发者来说,重载后的运算符也易于理解和使用。
加减乘除运算符重载
- 作类成员函数重载
#include <iostream>class human
{
public:human(){};human(int a ,int b):m_a(a),m_b(b){}//加减乘除运算符重载(成员函数)human operator*(const human& h){human h2;h2.m_a = this->m_a * h.m_a;h2.m_b = this->m_b * h.m_b;return h2;}int geta(){return this->m_a;}int getb(){return this->m_b;}private:int m_a;int m_b;};int main(int argc, char const *argv[])
{human h(10,20);human h1(2,10);//相当于 h.operator*(h1)human h3 = h * h1;std::cout << h3.geta() <<" "<< h3.getb()<<std::endl;return 0;
}
代码解读:
- 提供默认无参构造函数和函数初始化列表
human(){};human(int a ,int b):m_a(a),m_b(b){}- 加减乘除运算符重载(成员函数)这里指的是乘法
human operator*(const human& h){human h2;h2.m_a = this->m_a * h.m_a;h2.m_b = this->m_b * h.m_b;return h2;}
- 这里的参数是指常量引用:目的是不使用值传递的方式,防止对数据进行大量的拷贝,常量引用本质使用地址传递,地址通常占有4个字节,程序效率更高
- 这里的this指向调用该重载函数的哪个对象。
- 在栈区重新创建一个对象h,并将运算后的成员变量更新到该对象并返回。
human h3 = h * h1;这个相当于 h.operator*(h1)
std::cout << h3.geta() <<" "<< h3.getb()<<std::endl;因为成员变量m_a和m_b时私有变量,不能在类外访问,所以在类内使用函数来访问。
- 输出
这样就实现了类型为human的变量使用运算符来进行运算,20 = 10 *2 ;200 = 20*10
其他加减除法以此类推。
2.作全局函数重载
#include <iostream>class human
{friend human operator*(const human& p2, int val);
public:human(){};human(int a ,int b):m_a(a),m_b(b){}//加减乘除运算符重载(成员函数)human operator*(const human& h){human h2;h2.m_a = this->m_a * h.m_a;h2.m_b = this->m_b * h.m_b;return h2;}int geta(){return this->m_a;}int getb(){return this->m_b;}private:int m_a;int m_b;};
// 加减乘除运算符重载(全局函数)访问私有成员需要加friend声明
human operator*(const human& p2, int val)
{human temp;temp.m_a = p2.m_a *val;temp.m_b = p2.m_b * val;return temp;
}int main(int argc, char const *argv[])
{human h(10,20);human h1(2,10);//相当与 operator*(h,90)human h2 = h * 90;//相当于 h.operator*(h1)human h3 = h * h1;std::cout << h2.geta() <<" "<< h2.getb()<<std::endl;std::cout << h3.geta() <<" "<< h3.getb()<<std::endl;return 0;
}
代码解读:
- 加减乘除运算符重载(全局函数)访问私有成员需要加friend声明
human operator*(const human& p2, int val) {human temp;temp.m_a = p2.m_a *val;temp.m_b = p2.m_b * val;return temp; }该函数在类外定义,在类外定义的函数不能访问类内的私有变量,但是可以通过友元函数的方法来让类外定义的全局函数访问类内的私有变量。即
friend human operator*(const human& p2, int val);
human h2 = h * 90;相当与 operator*(h,90)调用的是全局函数。
输出
赋值运算符重载
返回值作为引用以实现链式赋值
#include <iostream>class human
{public:human(){};human(int a ,int b,int c):m_a(a),m_b(b),m_c(new int(c)){}//赋值运算符重载human& operator=(const human& h){if(this != &h){if(m_c != nullptr){delete m_c;m_c = nullptr;}}m_c = new int(*h.m_c);return *this;}int geta(){return this->m_a;}int getb(){return this->m_b;}int getc(){return *this->m_c;}
private:int m_a;int m_b;int* m_c;};int main(int argc, char const *argv[])
{human h(10,20,12);human h1(2,10,34);human h2(22,10,4);h = h1 = h2;std::cout <<h.getc()<<std::endl;return 0;
}
代码解读:
函数初始化列表来初始化成员变量
human(int a ,int b,int c):m_a(a),m_b(b),m_c(new int(c)){}赋值运算符重载
human& operator=(const human& h){if(this != &h){if(m_c != nullptr){delete m_c;m_c = nullptr;}}m_c = new int(*h.m_c);return *this;}首先使用this来判断调用该函数的对象是否和传入的对象是同一块内存,接着在判断调用该成员函数的对象中的成员变量m_c是否不为空,不为空则释放内存,再置为空。
两个对象不是同一块内存(this != &h)需要delete,再重新开辟内存。
这样作的目的是用于:如果对一个成员变量是指针的对象,将该指针指向的值进行修改时,需要先释放调用该重载函数的对象中指针变量,再为空,然后在m_c = new int(*h.m_c);重新开辟一块内存,内存的值是参数中对象的那个值。
原因:若不释放这块内存,在赋值操作完成后,原来的内存就会变成无法访问的 “孤儿” 内存,程序无法再释放它,从而造成内存泄漏。执行
delete m_c;就能正确释放这块内存,让系统可以重新使用它。两个对象是同一块内存(this == &h)不需要delete。
- 原因:当两个对象是统一块内存时,m_c这个指针变量指向的值是一样的,如果对其执行
delete m_c,那么在后面m_c = new int(*h.m_c);时使用*h.m_c时是非法的,因为这块内存已经被释放掉了,不能访问。为什么要m_c = new int(*h.m_c);
- 原因:编译器默认提供的是浅拷贝,对于一个含有指针变量的类中,浅拷贝会对这块内存多次释放,是不合法的,所以需要执行深拷贝来使得两个对象中的指针变量指向的值相同,但指针的值不同(地址不同)
- 有关【C++面向对象】封装(上):探寻构造函数的幽微之境-CSDN博客深拷贝,浅拷贝【C++面向对象】封装(上):探寻构造函数的幽微之境-CSDN博客
为什么return *this;返回值类型是human& 即引用。
- 原因:this指向调用该成员函数的那个对象,而*this是指的该对象,而返回值是human&引用是为了实现链式调用,而返回值是human不能实现链式赋值,因为他返回的是该对象的拷贝。
关系运算符重载
大于号运算符重载
#include <iostream>class human
{friend bool operator>(const human& h1,int val);
public:human(){};human(int a ,int b,int c):m_a(a),m_b(b),m_c(new int(c)){}//关系运算符重载bool operator>(const human& h1){if(this->m_a > h1.m_a && this->m_b > h1.m_b)return true;elsereturn false;}int geta(){return this->m_a;}int getb(){return this->m_b;}int getc(){return *this->m_c;}
private:int m_a;int m_b;int* m_c;};//关系运算符重载(全局函数)访问私有成员需要加friend声明
bool operator>(const human& h1,int val){if(val< h1.m_a && val < h1.m_b)return true;elsereturn false;
}
int main(int argc, char const *argv[])
{human h(10,20,12);human h1(2,10,34);//相当于 h.operator>(h1)if(h > h1)std::cout<<"h>h1"<<std::endl;elsestd::cout<<"h<h1"<<std::endl;//相当与 operator>(h,12)if(h > 12)std::cout<<"h>12"<<std::endl;elsestd::cout<<"h<12"<<std::endl;return 0;
}
代码解读:
上段代码分别用成员函数和全局函数的方法来实现对自定义类型的判断
- 对于
h > h1相当于 h.operator>(h1)
- 对于
h > 12相当与 operator>(h,12)
- 输出
相等运算符重载
#include <iostream>class human
{friend bool operator==(const human& h1,int val);
public:human(){};human(int a ,int b,int c):m_a(a),m_b(b),m_c(new int(c)){}//关系运算符重载bool operator==(const human& h1){if(this->m_a == h1.m_a && this->m_b == h1.m_b)return true;elsereturn false;}int geta(){return this->m_a;}int getb(){return this->m_b;}int getc(){return *this->m_c;}
private:int m_a;int m_b;int* m_c;};//关系运算符重载(全局函数)访问私有成员需要加friend声明
bool operator==(const human& h1,int val){if(val == h1.m_a)return true;elsereturn false;
}int main(int argc, char const *argv[])
{human h(10,20,12);human h1(2,10,34);//相当于 h.operator==(h1)if(h == h1)std::cout<<"二者相等"<<std::endl;elsestd::cout<<"二者不等"<<std::endl;//相当与 operator==(h,23)if(h == 23)std::cout<<"二者相等"<<std::endl;elsestd::cout<<"二者不等"<<std::endl;return 0;
}
代码解读:
上段代码分别用成员函数和全局函数的方法来实现对自定义类型的相等判断
- 对于
h == h1相当于相当于 h.operator==(h1)
- 对于
h == 23相当于 operator==(h,23)
- 输出
全部代码
#include <iostream>class human
{friend human operator*(const human& p2, int val);friend bool operator==(const human& h1,int val);friend bool operator>(const human& h1,int val);
public:human(){};human(int a ,int b,int c):m_a(a),m_b(b),m_c(new int(c)){}//加减乘除运算符重载(成员函数)human operator*(const human& h){human h2;h2.m_a = this->m_a * h.m_a;h2.m_b = this->m_b * h.m_b;return h2;}//关系运算符重载bool operator==(const human& h1){if(this->m_a == h1.m_a && this->m_b == h1.m_b)return true;elsereturn false;}//关系运算符重载bool operator>(const human& h1){if(this->m_a > h1.m_a && this->m_b > h1.m_b)return true;elsereturn false;}//赋值运算符重载human& operator=(const human& h){if(this != &h){if(m_c != nullptr){delete m_c;m_c = nullptr;}}m_c = new int(*h.m_c);return *this;}int geta(){return this->m_a;}int getb(){return this->m_b;}int getc(){return *this->m_c;}
private:int m_a;int m_b;int* m_c;};
// 加减乘除运算符重载(全局函数)访问私有成员需要加friend声明
human operator*(const human& p2, int val)
{human temp;temp.m_a = p2.m_a *val;temp.m_b = p2.m_b * val;return temp;
}//关系运算符重载(全局函数)访问私有成员需要加friend声明
bool operator==(const human& h1,int val){if(val == h1.m_a)return true;elsereturn false;
}
//关系运算符重载(全局函数)访问私有成员需要加friend声明
bool operator>(const human& h1,int val){if(val< h1.m_a && val < h1.m_b)return true;elsereturn false;
}
int main(int argc, char const *argv[])
{human h(10,20,12);human h1(2,10,34);//相当与 operator*(h,90)human h2 = h * 90;//相当于 h.operator*(h1)human h3 = h * h1;//相当于 h.operator==(h1)if(h == h1)std::cout<<"二者相等"<<std::endl;elsestd::cout<<"二者不等"<<std::endl;//相当与 operator==(h,23)if(h == 23)std::cout<<"二者相等"<<std::endl;elsestd::cout<<"二者不等"<<std::endl;//相当于 h.operator>(h1)if(h > h1)std::cout<<"h>h1"<<std::endl;elsestd::cout<<"h<h1"<<std::endl;//相当与 operator>(h,12)if(h > 12)std::cout<<"h>12"<<std::endl;elsestd::cout<<"h<12"<<std::endl;std::cout << h2.geta() <<" "<< h2.getb()<<std::endl;std::cout << h3.geta() <<" "<< h3.getb()<<std::endl;h = h1;std::cout <<h.getc()<<std::endl;return 0;
}
🔥个人主页 🔥
😈所属专栏😈

相关文章:
【C++面向对象】封装(下):探索C++运算符重载设计精髓
🔥个人主页 🔥 😈所属专栏😈 每文一诗 💪🏼 年年岁岁花相似,岁岁年年人不同 —— 唐/刘希夷《代悲白头翁》 译文:年年岁岁繁花依旧,岁岁年年看花之人却不相同 目录 C运…...
JVM初探——走进类加载机制|三大特性 | 打破双亲委派SPI机制详解
目录 JVM是什么? 类加载机制 Class装载到JVM的过程 装载(load)——查找和导入class文件 链接(link)——验证、准备、解析 验证(verify)——保证加载类的正确性 准备(Prepare&…...
[图论]Kruskal
Kruskal 本质:贪心,对边进行操作。存储结构:边集数组。适用对象:可为负权图,可求最大生成树。核心思想:最短的边一定在最小生成树(MST)上,对最短的边进行贪心。算法流程:对全体边集…...
UML-饮料自助销售系统(无法找零)序列图
一、题目: 在饮料自动销售系统中,顾客选择想要的饮料。系统提示需要投入的金额,顾客从机器的前端钱币口投入钱币,钱币到达钱币记录仪,记录仪更新自己的选择。正常时记录仪通知分配器分发饮料到机器前端,但可…...
Nginx Http配置整理
一、nginx 配置参数: server {#SSL 默认访问端口号为 443listen 443 ssl;#请填写绑定证书的域名server_name cloud.tencent.com; #请填写证书文件的相对路径或绝对路径ssl_certificate cloud.tencent.com_bundle.crt; #请填写私钥文件的相对路径或绝对路径ssl_cer…...
爬虫利器SpiderTools谷歌插件教程v1.0.0!!!web端JavaScript环境检测!!!
SpiderTools谷歌插件教程v1.0.0 一、SpiderTools简介二、下载通道三、插件介绍四、插件使用五、工具函数使用 一、SpiderTools简介 SpiderTools主要用于检测和监控网页的JavaScript运行环境。该插件可以帮助开发者更好地查看网页运行环境,特别是在处理复杂的前端环…...
计算机视觉算法实战——基于YOLOv8的农田智能虫情测报灯害虫种类识别系统开发指南
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 一、智能虫情监测领域概述 1.1 农业虫害防治现状 全球每年因虫害造成的粮食损失达20%-40%,我…...
14-算法打卡-哈希表-基本概念-第十四天
1 基本概念 1.1 哈希表 百度百科解释: 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快…...
趣味编程之分布式系统:负载均衡的“雨露均沾“艺术
#此篇文章由Deepseek大力支持😋 凌晨三点,西二旗某火锅店后厨—— “羊肉卷走3号桌!” “肥牛卷去7号!” “虾滑优先给VIP区!” 我蹲在传菜口的监控屏幕前,看着机器人服务生们忙而不乱地穿梭。突然间&am…...
第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
赛时参加的是Python组,这是赛后写的题解,还有两题暂时还不会,待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案:1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…...
考研数据结构之顺序查找、折半查找与分块查找详解(包含真题及解析)
考研数据结构之顺序查找、折半查找与分块查找详解 一、顺序查找(Sequential Search) 1.1 基本思想 顺序查找是最基础的查找算法,通过遍历数据集合逐个比较目标值与当前元素,直到找到匹配项或遍历结束。其核心特点是:…...
英文查重的时候参考文献显示重复是怎么回事?
像上图这样参考文献部分有颜色的情况,是属于参考文献没有排除干净的问题。 如何解决这样的问题? 首先第一步,先确认该报告是不是排除参考文献的版本; 第二步,如果是排除参考文献的版本,且参考文献仍然有…...
八股文---MySQl(3)
目录 12.事务的特性是什么?可以详细说一下吗? 回答 13并发事务带来哪些问题?怎么解决这些问题呢?MySQL的默认隔离级别是? 脏读:一个事务读到另外一个事务还没有提交的数据。 不可重复读:一个…...
基于labview的钢琴程序设计
部分程序如下 按照上图子vi更改输出频率即可 若需完整程序可以联系我...
国内网络设备厂商名单(List of Domestic Network Equipment Manufacturers)
国内网络设备厂商名单 运维工程师必须广泛熟悉国内外各大厂商的设备,深入掌握其应用场景、功能特点及优势。这不仅有助于在故障排查时迅速定位问题,还能在系统设计、优化与升级中做出更合理的决策。对设备特性的精准把握,能够显著提升运维效…...
基于CNN+ViT的蔬果图像分类实验
本文只是做一个简单融合的实验,没有任何新颖,大家看看就行了。 1.数据集 本文所采用的数据集为Fruit-360 果蔬图像数据集,该数据集由 Horea Mureșan 等人整理并发布于 GitHub(项目地址:Horea94/Fruit-Images-Datase…...
高级语言调用C接口(五)结构体(3)-arkts
上一篇文章提到了,arkts和C接口之前还有一个Napi层,这层代码最大的优势就是C/C编码,这样,我们只需要把数据通过Json格式传递到Napi层,Napi层再定义一个结构体并赋值即可。arkts层是TypeScript代码,想定义成…...
【虚幻C++笔记】接口
目录 概述创建接口 概述 简单的说,接口提供一组公共的方法,不同的对象中继承这些方法后可以有不同的具体实现。任何使用接口的类都必须实现这些接口。实现解耦解决多继承的问题 创建接口 // Fill out your copyright notice in the Description page o…...
【MCP】第一篇:MCP协议深度解析——大模型时代的“神经连接层“架构揭秘
【MCP】第一篇:MCP协议深度解析——大模型时代的"神经连接层"架构揭秘 一、什么是MCP?二、为什么需要MCP?三、MCP的架构四、MCP与AI交互的原理4.1 ReAct(Reasoning Acting)模式4.2 Function Calling 模式 五…...
实时模式下 libaom 与 x264 编码对比实验
前沿 理论基础:在相同视频质量下,AV1的压缩率比H.264高约30%-50%。实时模式:视频编码中的实时模式,其核心目标是平衡编码效率与延迟要求,尤其在视频会议、直播、实时通信等场景中至关重要。 低延迟要求:编…...
学习海康VisionMaster之矩形检测
这几天太忙了,好几天没有学习了,今天终于空下来了,继续学习之路吧。 一:进一步学习了 今天学习下VisionMaster中的矩形检测,这个一开始我以为是形态学方面的检测,实际操作下来其实还是边缘直线的衍生应用&…...
解决前端vue项目在linux上,npm install,node-sass 安装失败的问题
Unable to save binary /var/lib/jenkins/workspace/xxx/node_modules/node-sass/vendor/linux-x64-72 : Error: EACCES: permission denied, mkdir ‘/var/lib/jenkins/workspace/x/node_modules/node-sass/vendor’ 这个是node-sass安装失败导致的。 #将npm的默认仓库更改为…...
C Primer Plus 第6版 编程练习——第3章
1、通过试验(即编写带有此类问题的程序)观察系统如何处理整数上道、浮占数上溢和浮点数下溢的 int main(int argc, char** argv) {int intMax 2147483647;float floatMax 3.402823466e38f;float floatMin -3.402823466e38f;printf("intMax:%d, …...
十倍开发效率 - IDEA插件之 Mybatis Log Free
提高效率不是为了完成更多任务,而是为了有充足的时间摸鱼 快速体验 MyBatis Log Free 支持打印执行的 SQL(完整的SQL,没有占位符的)。 没有使用 MyBatis Log Free 的开启日志打印是这样的: 用了 MyBatis Log Free 后…...
手动安装 VMware Tools 并设置虚拟机共享 Windows 文件夹
前言:在当今数字化的工作环境中,虚拟机技术为我们提供了强大的灵活性和便利性。VMware 作为虚拟化领域的佼佼者,其虚拟机软件被广泛应用于开发、测试和日常工作中。然而,许多用户在使用 VMware 虚拟机时,会遇到一个常见…...
(免费)flask调用讯飞星火AI,实现websocket
本文章可借鉴学习,不可直接盗用 接入ai要获取ID,Secret,Key,和接口地址,由于我们服务接口类型是websocket,所以要获取相应的接口地址。(千万不要复制粘贴到http的了) 还要获取doma…...
ARINC818协议-持续
一、帧头帧尾 SOF 和 EOF 分别代表视频帧传输的开始与结束,它们在封装过程有多种状态,SOF 分为 SOFi 和 SOFn,EOF 分为 EOFt 和 EOFn。传输系统中的视频信息包括像素数据信 息和辅助数据信息,分别存储在有效数据中的对象 0 和对象…...
分布式笔记(一)
分布式系统问题 并发性 没有全局时钟 故障独立性 分布式系统概念 分布式优势 资源共享、开放性、并发性、可扩展性、容错性 问题挑战 分布式系统总部特性很难了解 分布式系统响应不可预知 不能自顶向下 设计原则 透明性 开放性:按照普遍标准 可扩展性…...
linux常用基础命令_最新版
echo off setlocal enabledelayedexpansion :: Copyright © 2025 xianwen.deng :: All rights reserved. :: 591278546qq.com :: Version: 1.0 for /f “tokens2 delims:” %%a in (‘chcp’) do set “codepage%%a” set codepage!codepage: ! echo Codepage: !codepag…...
2021-11-09 C++三位数平方含有该数
缘由求解,运算函数,哪位大神教一下-编程语言-CSDN问答 void 三位数平方含有该数() {//缘由https://ask.csdn.net/questions/7560152?spm1005.2025.3001.5141int a 100, aa 1000, f 0;while (a < aa){f a*a;while (f > a)if ((f - a) % aa)f …...




