C++面向对象学习笔记五

本文主要讲解运算符重载,由于白鳯大佬没有具体讲解,所以本文自行补充了运算符重载的相关知识

目录

文章目录

前言

运算符重载

加号运算符重载

左移运算符重载

递增运算符重载 

总结


前言

本文主要对于运算符重载进行探讨,分别对于成员函数重载和全局函数重载(友元函数重载)进行讨论。


运算符重载

运算符重载是C++中的一项强大功能,它允许您为自定义的类或结构体定义特定的行为,以响应与内置类型相似的操作符。通过重载运算符,您可以实现自定义类型之间的数学运算、比较、位操作等。

运算符重载使用operator关键字后跟要重载的运算符来实现。例如,+表示加法运算符,-表示减法运算符等。

运算符重载一般分为成员函数重载和全局函数重载

以下是一些常见的需要进行运算符重载的情况:

  1. 算术运算符:例如 +-*/%
  2. 比较运算符:例如 ==!=<><=>=
  3. 赋值运算符:例如 =+=-=*=/=
  4. 位操作运算符:例如 &|^
  5. 下标操作符:[]
  6. 函数调用操作符:()

对于每个需要进行重载的运算符,您可以根据需求定义适当的成员函数或非成员函数。成员函数形式在对象本身上调用该操作,而非成员函数形式将两个对象作为参数传递。

请注意,在进行运算符重载时,请遵循一些最佳实践和规则:

  1. 不要改变原始对象的状态(如果不是必要的)。
  2. 避免创建歧义或混乱的重载操作。
  3. 考虑使用友元函数来实现某些运算符重载,以便访问私有成员。

运算符重载是C++语言中的一项强大功能,可以提高代码的可读性和表达能力。

加号运算符重载

加号运算符(+)可以在C++中进行重载,使其适用于自定义类型的对象。要重载加号运算符,您可以使用成员函数或非成员函数的形式。

成员函数形式:本质为 p3 = p1.operator+(p2)

class MyClass {
public:MyClass operator+(MyClass& other) {// 在这里实现加法操作,并返回结果}
};
#include <iostream>class Complex {
private:double real;double imag;public:Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}Complex operator+(const Complex& other) const {return Complex(real + other.real, imag + other.imag);}void display() const {std::cout << "(" << real << " + " << imag << "i)" << std::endl;}
};int main() {Complex c1(2.5, 3.7);Complex c2(1.8, -2.9);Complex sum = c1 + c2; // 使用重载的加号运算符sum.display(); // 输出:(4.3 + 0.8i)return 0;
}

全局函数形式:(友元函数访问私有成员)本质为 p3 = operator+(p1,p2)

class MyClass {
public:};MyClass operator+(const MyClass& obj1, const MyClass& obj2) {// 在这里实现加法操作,并返回结果}
#include <iostream>class Complex {
private:double real;double imag;public:Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}// 声明友元函数以便访问私有成员friend Complex operator+(const Complex& c1, const Complex& c2);void display() const {std::cout << "(" << real << " + " << imag << "i)" << std::endl;}
};Complex operator+(const Complex& c1, const Complex& c2) {return Complex(c1.real + c2.real, c1.imag + c2.imag);
}int main() {Complex c1(2.5, 3.7);Complex c2(1.8, -2.9);Complex sum = c1 + c2; // 使用重载的加号运算符sum.display(); // 输出:(4.3 + 0.8i)return 0;
}

俩个代码实现内容一样,主要一个是成员函数,一个全局函数,全局函数需要成为友元函数来访问类的私有数据成员。 

同时运算符重载也可以发生函数重载 

左移运算符重载

如果我们有一个person类,建立一个对象p,当我们想直接使用cout<<p<<endl;来输出对象p中的内容似乎并不能直接实现,C++并不认识这个类,也不知道如何输出。

这里我们就可以使用左移运算符重载了,与上面的加号运算符一样,左移运算符同样是以operato<<形式实现的,这里我们仍然可以分为成员函数重载和全局函数重载来分别实现一下。

当我们按照成员函数来写时,就会发现一个问题,首先你不能给自己传入p,即p.operator<<(p),然后我们再使用p.operator<<(cout),而这样简化的版本就是p<<cout,与我们想要的cout<<p相反了,所以我们不使用成员函数来实现左移运算符,而使用全局函数。

void operator<<(cout)
{
//简化完事 p << cout
}

 如果用全局函数首先要知道的事,cout是输出流对象,即ostream对象

使用operator<<(ostream &cout,person &p)进行函数重载,简化完事cout<<p

至于为什么不用void空值,而是ostream &,是因为,当你主函数使用函数重载输出后,如果返回的事空值,就不能继续追加输出,例如<<endl;补上换行,因为cout后面一直能连续使用<<是链式编程,需要返回的还是cout,即返回ostream输出流。

class preson 
{
private: 
string p_name;
int p_age;
public:
friend ostream & operator<<(ostream &cout,person &p);
}
ostream & operator<<(ostream &cout,person &p)
{cout<<"p_name"<<p.p_name<<"p_age"<<p._age<<endl;
}

递增运算符重载 

递增运算符重载,即要对++进行运算符重载

跟C++中的++a,a++一样,递增运算符重载也要分为前置递增和后置递增的重载

解决下述代码中几个重点问题

1、函数重载的返回类型就是自己建立的Integer类型是因为,如果有个对象num,当你想要实现对num++或者++num直接输出,类似于a=1;cout<<a++<<endl;的操作时,你需要返回Integer类型,否则返回空值是没有输出的

2、为什么前置递增返回值类型引用了,而后置递增返回值类型没有引用。

后置传递如果使用引用,那么值就错了,要返回递增前的值

这个主要是了解++运算符实现的本质
a=1;

cout<<++(++a)<<endl;  这个是对的,说明前置运算符计算本质是引用,对一个数修改

cout<<(a++)++<<endl;  这个是错的,说明后置运算符计算本质是值传递,无法二次修改

3、下述代码偷懒了,应该演示一下++num,num++的输出,而不是使用成员函数getValue来实现,其实只要将左移运算符重载一下就可以了,按照已讲过的方法实现即可 

#include <iostream>
using namespace std;class Integer {
private:int value;
public:Integer(int val) : value(val) {}// 前置递增运算符重载Integer& operator++() {++value;return *this;}// 后置递增运算符重载Integer operator++(int) {Integer temp(value);++value;return temp;}int getValue() const {return value;}
};int main() {Integer num1(5);cout << "初始值: " << num1.getValue() << endl;// 前置递增++num1;cout << "前置递增后的值: " << num1.getValue() << endl;// 后置递增Integer num2 = num1++;cout << "后置递增后的值: " << num2.getValue() << endl;cout << "num1当前的值: " << num1.getValue() << endl;return 0;
}

总结

本文主要对运算符重载进行了探讨,主要讲述了运算符重载分为成员函数重载和全局函数重载(友元函数重载)这样的操作,并举例加号,左移以及递增运算符的重载方法和一些注意事项。

通过上述的讲解,可以实现更多的运算法重载的方法,当然还有很多运算符重载值得我们探讨,本文讲述的内容也比较有限。

推荐学习博客 https://xxetb.xetslk.com/s/4GgGz6

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

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

相关文章

JVM 类加载机制

JVM 类加载机制分为五个部分&#xff1a;加载&#xff0c;验证&#xff0c;准备&#xff0c;解析&#xff0c;初始化&#xff0c;下面我们就分别来看一下这五个过程。 加载 加载是类加载过程中的一个阶段&#xff0c;这个阶段会在内存中生成一个代表这个类的 java.lang.class 对…

C语言经典例题-9

1.简单计算器 题目描述&#xff1a; KK实现一个简单计算器&#xff0c;实现两个数的“加减乘除”运算&#xff0c;用户从键盘输入算式“操作数1运算符操作数2”&#xff0c;计算并输出表达式的值&#xff0c;如果输入的运算符号不包括在&#xff08;、-、*、/&#xff09;范围…

Navicat Premium安装pojie版

下载、安装mysql&#xff0c;环境变量配置 1、官网下载mysql&#xff1a;https://www.mysql.com/downloads/ 下载成功&#xff0c;进行安装 一直点下一步 验证&#xff0c;开始中搜索mysql 说明安装成功 环境变量配置 默认安装路径C:\Program Files\MySQL …

向量检索和关键字检索的区别?

向量检索&#xff08;Vector Retrieval&#xff09;和关键字检索&#xff08;Keyword Retrieval&#xff09;是信息检索领域中常见的两种检索方法&#xff0c;它们有一些显著的区别&#xff1a; 1、检索方式&#xff1a; 向量检索&#xff1a;向量检索是基于文档和查询之间的相…

Kafka和Spark Streaming的组合使用学习笔记(Spark 3.5.1)

一、安装Kafka 1.执行以下命令完成Kafka的安装&#xff1a; cd ~ //默认压缩包放在根目录 sudo tar -zxf kafka_2.12-2.6.0.tgz -C /usr/local cd /usr/local sudo mv kafka_2.12-2.6.0 kafka-2.6.0 sudo chown -R qiangzi ./kafka-2.6.0 二、启动Kafaka 1.首先需要启动K…

计算机毕业设计Python地震预测系统 地震数据分析可视化 地震爬虫 大数据毕业设计 Flink Hadoop 深度学习 机器学习 人工智能 知识图谱

学生信息 姓名&#xff1a;  祁浩 题目&#xff1a; 基于Python的中国地震数据分析与可视化系统的设计与实现 学号&#xff1a; 2020135211 班级&#xff1a; 20大数据本科2班 指导教师&#xff1a; 刘思思 答辩过程 学生开题陈述 为了让学习者更好的了解了解地震…

Coze扣子开发指南:AI零代码编程创建插件

在Coze扣子中创建插件&#xff0c;有两种方式&#xff0c;一是用API&#xff0c;具体方式参照上一篇文章《Coze扣子开发指南&#xff1a;用免费API自己创建插件》&#xff0c;还有一种方式就是编程&#xff0c;不过有了AI的帮助&#xff0c;即使不会编程的人&#xff0c;也可以…

HarmonyOS开发案例:【生活健康app之获取成就】(3)

获取成就 本节将介绍成就页面。 功能概述 成就页面展示用户可以获取的所有勋章&#xff0c;当用户满足一定的条件时&#xff0c;将点亮本页面对应的勋章&#xff0c;没有得到的成就勋章处于熄灭状态。共有六种勋章&#xff0c;当用户连续完成任务打卡3天、7天、30天、50天、…

用大于meilisearch-java-0.7.0.jar的报错的解决

Elasticsearch 做为老牌搜索引擎&#xff0c;功能基本满足&#xff0c;但复杂&#xff0c;重量级&#xff0c;适合大数据量。 MeiliSearch 设计目标针对数据在 500GB 左右的搜索需求&#xff0c;极快&#xff0c;单文件&#xff0c;超轻量。 所以&#xff0c;对于中小型项目来说…

阿里云服务器在线安装nginx

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《nginx实战》 目录 内容简介 安装步骤 1.root用户登录连接阿里云服务器 2.在usr/local下新建nginx目录 3.安装 1安装下载工具 2下载nginx压缩包 3解压 4安装nginx依赖的库 5编译并安装 6启动nginx 7开启…

蓝桥杯-递增三元组(三种解法,二分, 双指针, 前缀和)

给定三个整数数组 A[A1,A2,…AN], B[B1,B2,…BN], C[C1,C2,…CN], 请你统计有多少个三元组 (i,j,k) 满足&#xff1a; 1≤i,j,k≤N Ai<Bj<Ck 输入格式 第一行包含一个整数 N。 第二行包含 N 个整数 A1,A2,…AN。 第三行包含 N 个整数 B1,B2,…BN。 第四行包含 N …

【图像畸变校正】

接上篇文章&#xff1a;【鱼眼&#xff0b;普通相机】相机标定 附代码&#xff1a; 方法一&#xff1a; 使用cv2.undistort """Create May 11, 2024author Wang Jiajun """import cv2 import numpy as npdef correct(img,camera_fileE:/cali…

怎么使用远程桌面传输文件?

微软提供的远程桌面功能是一项强大的工具&#xff0c;可让您在同一网络下远程访问和管理其他计算机。除了远程控制&#xff0c;它还支持文件传输功能&#xff0c;为Windows用户提供了极大的便利。在接下来的内容中&#xff0c;我们将介绍如何使用远程桌面传输文件。 如何从远程…

PADS:生成自交叉平面区域

根据板外形铺铜方法&#xff1a; pads根据板外形铺铜_铺铜如何根据板子形状改变-CSDN博客 根据板外形创建平面区域出现问题&#xff1a; 解决方法&#xff1a;去找结构&#xff0c;让他把出图之前把线合并了

【数据结构】顺序栈

顺序栈 一、相关概念 栈和队列是操作受限的线性表&#xff0c;是限定性的数据结构&#xff1b;栈分为顺序栈和链式栈栈只能在一端进行操作&#xff08;插入、删除&#xff09;栈是限定仅在表尾进行插入或删除操作的线性表&#xff0c;因此&#xff0c;对栈来说&#xff0c;表…

https免费证书获取

获取免费证书的网址&#xff1a; Certbot 1. 进入你的linux系统&#xff0c;先安装snapd&#xff0c; yum install snapd 2. 启动snapd service snapd start 3.安装 Certbot snap install --classic certbot 注意如下出现此错误时&#xff0c;需要先建立snap 软连接后&am…

山东大学软件学院创新项目实训开发日志——第11周

山东大学软件学院创新项目实训开发日志——第11周 项目名称&#xff1a;ModuFusion Visionary&#xff1a;实现跨模态文本与视觉的相关推荐 -------项目目标&#xff1a; 本项目旨在开发一款跨模态交互式应用&#xff0c;用户可以上传图片或视频&#xff0c;并使用文本、点、…

Golang | Leetcode Golang题解之第84题柱状图中最大的矩形

题目&#xff1a; 题解&#xff1a; func largestRectangleArea(heights []int) int {n : len(heights)left, right : make([]int, n), make([]int, n)for i : 0; i < n; i {right[i] n}mono_stack : []int{}for i : 0; i < n; i {for len(mono_stack) > 0 &&am…

SQLite索引名称重复(index already exists)

文章目录 概述报错信息解决方案 概述 SQLite中创建单列索引的方式&#xff0c;跟MySQL类似&#xff1a; CREATE INDEX index_name ON table_name (column_name);但是也有不同的地方&#xff1a; MySQL中索引名称在表内部不重复即可。 SQLite中索引名称在整个库中必须是不重复…

整理项目中经常用到的正则

目录 1、手机号码 2、Email 邮箱 3、QQ 号码 4、非零正整数 5、URL 地址 6、身份证号 项目中难免会经常使用到表单&#xff0c;而表单项校验就需要用到正则&#xff0c; 所以整理总结一下自己项目中使用比较频繁的一些正则校验逻辑。 正则表达式 是由一些具有特殊含义的…