【C++】揭开运算符重载的神秘面纱
目录
一、引言
优点
二、介绍
1.定义
2.语法
三、示例
1.加法运算符重载
2.一元运算符重载
3.友元函数
4.流插入和流提取
5.自增自减运算符
总结
一、引言
何为运算符重载?运算符重载,是C++中的一项强大特性,赋予了程序员在自定义类型上实现更直观、灵活的操作的能力。通过运算符重载,我们可以为自定义的类或结构体定义标准运算符的行为,使得代码更加富有表达力,更接近自然语言的阐述方式。下面我们来具体谈谈运算符重载的有关知识,揭开她的神秘面纱。
优点
在实际编程中,运算符重载发挥了重要的作用,主要体现在以下几个方面:
可读性提升: 运算符重载使得代码更贴近问题领域的语言,使得代码读起来更自然、更易理解。例如,通过重载加法运算符,我们可以直接使用 object1 + object2 表达对象相加的语义,而无需调用繁琐的方法或函数。
灵活性增强: 自定义类型的运算符重载允许我们定义对象之间的交互方式。这种灵活性使得代码更容易适应不同的需求和上下文,提高了代码的通用性和可复用性。
语法糖的应用: 运算符重载为代码添加了一些语法糖,使得代码更加简洁、优雅。这不仅提高了代码的可读性,还有助于减少冗余代码的数量。
自定义类型的自然表达: 通过运算符重载,我们可以使自定义类型的对象表现出与内置类型相似的行为,使得使用这些类型的代码更加自然而流畅。
二、介绍
1.定义
通过运算符重载,用户可以为自己创建的类或结构体定义与标准运算符相对应的操作,使得这些类型的对象可以使用像内置类型一样的简洁语法来执行操作。
例如,对于自定义类 Complex 表示复数,我们可以通过运算符重载实现两个复数对象的加法:
class Complex {
public:Complex operator+(const Complex& other) const {Complex result;result.real = this->real + other.real;result.imaginary = this->imaginary + other.imaginary;return result;}private:double real;double imaginary;
};
在上述例子中,通过重载 + 运算符,我们使得 Complex 类的对象可以使用 + 运算符执行相应的复数加法,使得代码更加直观和易读。
2.语法
运算符重载的基本语法取决于编程语言,以下是C++中的一些关键点:
-
运算符重载函数的名称由
operator关键字后接要重载的运算符决定。例如,要重载加法运算符,使用operator+。MyClass operator+(const MyClass& obj) const {// 实现运算符行为 } -
运算符重载函数可以是成员函数,也可以是友元函数。成员函数的左操作数是调用对象,右操作数是函数参数。友元函数不属于类,但可以访问类的私有成员。
-
参数的类型通常是按值传递或按常量引用传递,取决于是否需要修改参数的值。返回类型通常是一个新的对象,以便支持链式调用。
通过在类中定义运算符重载函数,我们可以为用户自定义类型赋予标准运算符的语义,使得这些类型可以通过与内置类型相似的语法进行操作,提高了代码的可读性和表达力。
三、示例
1.加法运算符重载
#include <iostream>class Point {
public:Point(double x, double y) : x(x), y(y) {}// 重载加法运算符作为成员函数Point operator+(const Point& other) const {return Point(this->x + other.x, this->y + other.y);}// 显示坐标void display() const {std::cout << "(" << x << ", " << y << ")" << std::endl;}private:double x;double y;
};int main() {Point p1(1.0, 2.0);Point p2(3.0, 4.0);// 使用重载的加法运算符Point result = p1 + p2;std::cout << "Result: ";result.display();return 0;
}
在这个例子中,我们将加法运算符 + 作为成员函数重载。通过这种方式,我们可以使用 p1 + p2 来直接实现两个点的坐标相加,使得代码更加简洁和直观。
2.一元运算符重载
考虑一个表示复数的类 Complex,我们可以通过重载一元运算符实现复数的取负操作:
class Complex {
public:Complex(double real, double imaginary) : real(real), imaginary(imaginary) {}Complex operator-() const {return Complex(-real, -imaginary);}void display() const {std::cout << real << " + " << imaginary << "i" << std::endl;}private:double real;double imaginary;
};int main() {Complex c1(2.0, 3.0);Complex negativeC1 = -c1;std::cout << "Original: ";c1.display();std::cout << "Negation: ";negativeC1.display();return 0;
}
在上述例子中,通过重载一元运算符 -,我们实现了复数的取负操作,使得 negativeC1 = -c1 变得简洁易读。
3.友元函数
假设我们有一个包含私有成员的类 PrivateClass,我们可以使用友元函数来重载某个运算符,以便访问私有成员:
class PrivateClass {
private:int value;public:PrivateClass(int val) : value(val) {}// 声明友元函数friend PrivateClass operator+(const PrivateClass& obj1, const PrivateClass& obj2);
};// 定义友元函数
PrivateClass operator+(const PrivateClass& obj1, const PrivateClass& obj2) {return PrivateClass(obj1.value + obj2.value);
}int main() {PrivateClass obj1(5);PrivateClass obj2(10);PrivateClass result = obj1 + obj2;// 此处访问了 PrivateClass 的私有成员 valuestd::cout << "Result: " << result.value << std::endl;return 0;
}
在上述例子中,通过将友元函数声明为类的友元,我们可以在函数中访问 PrivateClass 的私有成员。友元函数通常用于需要访问类的私有成员的情况。
4.流插入和流提取
流插入运算符 << 和流提取运算符 >> 的重载通常用于自定义对象的输出和输入格式。以下是一个示例,演示如何在类 Person 中重载这两个运算符:
#include <iostream>
#include <string>class Person {
public:Person(std::string name, int age) : name(name), age(age) {}// 重载流插入运算符 <<friend std::ostream& operator<<(std::ostream& os, const Person& person) {os << "Name: " << person.name << ", Age: " << person.age;return os;}// 重载流提取运算符 >>friend std::istream& operator>>(std::istream& is, Person& person) {std::cout << "Enter name: ";is >> person.name;std::cout << "Enter age: ";is >> person.age;return is;}private:std::string name;int age;
};int main() {Person person("John", 25);// 使用流插入运算符输出对象std::cout << "Person Information: " << person << std::endl;// 使用流提取运算符输入对象std::cout << "Enter new person information:" << std::endl;std::cin >> person;std::cout << "Updated Person Information: " << person << std::endl;return 0;
}
在这个例子中,我们通过重载 << 和 >> 运算符,使得对象 Person 可以通过流的方式输出和输入。这样,我们可以使用 std::cout << person 来输出人物信息,以及使用 std::cin >> person 来从用户输入中读取新的信息。
5.自增自减运算符
自增和自减运算符 ++ 和 -- 可以作为前缀和后缀进行重载。以下是一个示例,演示如何在类 Counter 中重载这两个运算符:
#include <iostream>class Counter {
public:Counter(int value) : count(value) {}// 前缀自增运算符 ++Counter& operator++() {count++;return *this;}// 后缀自增运算符 ++Counter operator++(int) {Counter temp = *this;count++;return temp;}// 前缀自减运算符 --Counter& operator--() {count--;return *this;}// 后缀自减运算符 --Counter operator--(int) {Counter temp = *this;count--;return temp;}// 获取计数值int getCount() const {return count;}private:int count;
};int main() {Counter counter(5);// 前缀自增运算符 ++++counter;std::cout << "After prefix increment: " << counter.getCount() << std::endl;// 后缀自增运算符 ++Counter result = counter++;std::cout << "After postfix increment: " << result.getCount() << std::endl;// 前缀自减运算符 ----counter;std::cout << "After prefix decrement: " << counter.getCount() << std::endl;// 后缀自减运算符 --result = counter--;std::cout << "After postfix decrement: " << result.getCount() << std::endl;return 0;
}
在这个例子中,我们通过重载前缀和后缀的自增和自减运算符,使得 Counter 类的对象可以方便地进行增加和减少操作。
总结
运算符重载是一种强大的编程技术,允许用户定义的类型通过标准运算符执行自定义的操作。通过运算符重载,代码变得更加直观,可读性提高,使得类和对象的使用更加自然。在实际应用中,运算符重载常用于数学计算、矩阵操作等领域,提高了代码的灵活性和可维护性。
如果觉得这篇博客对你有帮助,可以点点关注哟,留下你们的点赞评论收藏,你们的关注与点赞就是我最大的鼓励~~😉😉我会持续创作滴!小海在这里谢谢各位~~
相关文章:
【C++】揭开运算符重载的神秘面纱
目录 一、引言 优点 二、介绍 1.定义 2.语法 三、示例 1.加法运算符重载 2.一元运算符重载 3.友元函数 4.流插入和流提取 5.自增自减运算符 总结 一、引言 何为运算符重载?运算符重载,是C中的一项强大特性,赋予了程序员在自定义类…...
竞赛保研 基于LSTM的天气预测 - 时间序列预测
0 前言 🔥 优质竞赛项目系列,今天要分享的是 机器学习大数据分析项目 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/po…...
前端常用的开发工具
前端常用的开发工具🔖 文章目录 前端常用的开发工具🔖1. Snipaste--截图工具2. ScreenToGif--gif图片录制3. Typora--Markdown编辑器4. notepad--文本代码编辑器5. uTools--多功能工具6. EV录屏--录屏软件7. Xmind--思维导图8. Apifox -- 接口调试9. Tor…...
鸿蒙开发语言介绍--ArkTS
1.编程语言介绍 ArkTS是HarmonyOS主力应用开发语言。它在TypeScript (简称TS)的基础上,匹配ArkUI框架,扩展了声明式UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。 2.TypeScript简介 自行补充TypeScript知识吧。h…...
关于“Python”的核心知识点整理大全36
目录 13.4.4 向下移动外星人群并改变移动方向 game_functions.py alien_invasion.py 13.5 射杀外星人 13.5.1 检测子弹与外星人的碰撞 game_functions.py alien_invasion.py 13.5.2 为测试创建大子弹 13.5.3 生成新的外星人群 game_functions.py alien_invasion.py …...
安装nodejs,配置环境变量并将npm设置淘宝镜像源
安装nodejs并将npm设置淘宝镜像源 1. 下载nodejs 个人不喜欢安装包,所以是下载zip包的方式。这里我下载的node 14解压包版本 下载地址如下:https://nodejs.org/dist/v14.15.1/node-v14.15.1-win-x64.zip 想要其他版本的小伙伴去https://nodejs.org/di…...
12.18构建哈夫曼树(优先队列),图的存储方式,一些细节(auto,pair用法,结构体指针)
为结构体自身时,用.调用成员变量;为结构体指针时,用->调用成员变量 所以存在结构体数组时,调用数组元素里的成员变量,就是要用. 结构体自身只有在new时才会创建出来,而其指针可以随意创建 在用new时&…...
《Python》面试常问:深拷贝、浅拷贝、赋值之间的关系(附可变与不可变)【用图文讲清楚!】
背景 想必大家面试或者平时学习经常遇到问python的深拷贝、浅拷贝和赋值之间的区别了吧?看网上的文章很多写的比较抽象,小白接收的难度有点大,于是乎也想自己整个文章出来供参考 可变与不可变 讲深拷贝和浅拷贝之前想讲讲什么是可变数据类型…...
使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错问题
目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序,查看库与库的依赖关系,查看出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总(专栏文章列表&…...
Python编程题目答疑「Python一对一辅导考试真题解析」
你好,我是悦创。 待会更新~ 更新计划 答案 题目 记得点赞收藏! 题目 之后更新 Solution Question 1 # 读取输入 a float(input("请输入实数 a: ")) b float(input("请输入实数 b: ")) c float(input("请输…...
Python---搭建Python自带静态Web服务器
1. 静态Web服务器是什么? 可以为发出请求的浏览器提供静态文档的程序。 平时我们浏览百度新闻数据的时候,每天的新闻数据都会发生变化,那访问的这个页面就是动态的,而我们开发的是静态的,页面的数据不会发生变化。 …...
在服务器上部署SpringBoot项目jar包
以下是在服务器上部署Spring Boot项目jar包的步骤: 打包项目: 使用IDEA或者命令行工具(如Maven或Gradle)将Spring Boot项目打包为一个可执行的jar文件。如果使用Maven,可以在项目的根目录下运行以下命令来打包项目&…...
[python]python实现对jenkins 的任务触发
目录 关键词平台说明背景一、安装 python-jenkins 库二、code三、运行 Python 脚本四、注意事项 关键词 python、excel、DBC、jenkins 平台说明 项目Valuepython版本3.6 背景 用python实现对jenkins 的任务触发。 一、安装 python-jenkins 库 pip install python-jenkin…...
Python生成圣诞节贺卡-代码案例剖析【第18篇—python圣诞节系列】
文章目录 ❄️Python制作圣诞节贺卡🐬展示效果🌸代码🌴代码剖析 ❄️Python制作圣诞树贺卡🐬展示效果🌸代码🌴代码剖析🌸总结 🎅圣诞节快乐! ❄️Python制作圣诞节贺卡 …...
深度剖析Ajax实现方式(原生框架、JQuery、Axios,Fetch)
Ajax学习 简介: Ajax 代表异步 JavaScript 和 XML(Asynchronous JavaScript and XML)的缩写。它指的是一种在网页开发中使用的技术,通过在后台与服务器进行数据交换,实现页面内容的更新,而无需刷新整个…...
任天堂,steam游戏机通过type-c给VR投屏与PD快速充电的方案 三type-c口投屏转接器
游戏手柄这个概念,最早要追溯到二十年前玩FC游戏的时候,那时候超级玛丽成为了许多人童年里难忘的回忆,虽然长大了才知道超级玛丽是翻译错误,应该是任天堂的超级马里奥,不过这并不影响大家对他的喜爱。 当时FC家用机手柄…...
Flink系列之:Checkpoints 与 Savepoints
Flink系列之:Checkpoints 与 Savepoints 一、概述二、功能和限制 一、概述 从概念上讲,Flink 的 savepoints 与 checkpoints 的不同之处类似于传统数据库系统中的备份与恢复日志之间的差异。 Checkpoints 的主要目的是为意外失败的作业提供恢复机制。 …...
【优质书籍推荐】LoRA微调的技巧和方法
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…...
Linux一行命令配置jdk环境
使用方法: 压缩包上传 到/opt, 更换命令中对应的jdk包名即可。 注意点:jdk-8u151-linux-x64.tar.gz 解压后名字是jdk1.8.0_151 sudo tar -zxvf jdk-8u151-linux-x64.tar.gz -C /opt && echo export JAVA_HOME/opt/jdk1.8.0_151 | sudo tee -a …...
从0开始刷剑指Offer
剑指Offer题解 剑指 Offer 11. 旋转数组的最小数字 思路: 二分O(logn) class Solution {public int stockManagement(int[] stock) {int l 0;int r stock.length - 1;while(l < r && stock[0] stock[r]) r --;if(stock[r] > stock[l]) return stock[0];whi…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
