【C++】类和对象之运算符重载(三)

前言:在前面我们知道在类和对象中有六个默认成员函数,并学习了其中三个构造函数、析构函数、拷贝构造函数,今天我们将进一步的学习.赋值运算符重载。

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:高质量C++学习 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


目录标题

  • 运算符重载
    • 全局的operator
    • 局部的operator
    • 显示重载
    • 注意事项


运算符重载

运算符重载的概念:C++运算符重载是指在C++中可以自定义操作符的含义和行为。通过运算符重载,可以使用相同的操作符来执行不同类的对象的操作,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

C++中可以重载的运算符有:

  • 算术运算符(+、-、*、/、%等)
  • 关系运算符(==、!=、<、>、<=、>=等)
  • 逻辑运算符(!、&&、||等)
  • 位运算符(&、|、^等)
  • 赋值运算符(=、+=、-=等)
  • 自增自减运算符(++、–等)
  • 下标运算符([])
  • 函数调用运算符(())

要重载一个运算符,需要使用运算符关键字operator,以及重载函数的名称和参数。重载函数可以作为类的成员函数,也可以作为全局函数


函数原型返回值类型 operator操作符(参数列表)
格式如下:

<返回类型说明符> operator <运算符符号>(<参数表>)
{<函数体>}

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* :: sizeof ?: . 注意以上5个运算符不能重载。

全局的operator

以下是一个全局重载等于运算符的示例:

class Date
{
public:Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << "year = " << this->_year << " month = " << this->_month << " day = " << this->_day << endl;}
public://这里一定得是共有,不然外部无法访问int _year;int _month;int _day;
};bool operator==(const Date& s1,const Date& s2)
{return s1._year == s2._year &&s1._month == s2._month &&s1._day == s2._day;
}int main()
{Date d1;Date d2(2024, 2, 4);Date d3(d2);if (d1 == d2)//判断d1和d2是否相等{cout << "d1 == d2" << endl;}else{cout << "d1 != d2" << endl;}if (d2 == d3){cout << "d2 == d3" << endl;}else{cout << "d3 != d2" << endl;}return 0;
}

在这里插入图片描述
这里作者强调一下重载函数接收参数时候为什么要加上const修饰,因为我们在引用的时候,如果不加上const,就如下面这个例子一样,有的人写代码时候可能没有注意,一不小心就把原本的对象的值给修改了,所以我们接收参数的时候通常加上const对它进行修饰。

class Date
{
public:Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << "year = " << this->_year << " month = " << this->_month << " day = " << this->_day << endl;}
public://这里一定得是共有,不然外部无法访问int _year;int _month;int _day;
};
void operator+(Date& s1,Date& s2)//重载
{s2._year = s1._year++;
}int main()
{Date d1;Date d2(2024, 2, 4);cout << "重载前" << endl;cout << "d1:";d1.Print();cout << "d2:";d2.Print();d2 + d1;cout << "重载后" << endl;cout << "d1:";d1.Print();cout << "d2:";d2.Print();return 0;
}

在这里插入图片描述

局部的operator

当然了光说不做,等于白说,以下是一个局部重载等于运算符的示例:

#include <iostream>
#include <stdbool.h>
using namspace std;
class Date
{
public:Date(int year = 2024,int month = 2,int day = 1)//初始化{_year = year;_month = month;_day = day;}void Print(){cout << "year = " << this->_year << " month = " << this->_month << " day = " << this->_day << endl;}   bool operator==(const Date& s1)//在类中成员函数的第一个参数为隐藏的this,因此我们只需要一个参数{return _year == s1._year &&_month == s1._month &&_day == s1._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(2024, 2, 4);Date d3(d2);if (d1 == d2)//判断d1和d2是否相等{cout << "d1 == d2" << endl;}else{cout << "d1 != d2" << endl;}if (d2 == d3){cout << "d2 == d3" << endl;}else{cout << "d3 != d2" << endl;}return 0;
}

这里很多人会很疑惑,为什么你这里只有一个参数,你这一个参数怎么比较两个数是不是相等?这里作者来给大家解释一下,其实本质上这里有一个隐式的this指针我们在前面也提到过,如果不懂什么是this指针的可以去看看博主前面的文章。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


别看这里可以赋值,但是我们思考一下,能不能连续赋值呢?

d1 = d2 = d3;//如果我们要这样赋值呢?

怎么会出现下面这个情况?我们不是赋值了嘛?

在这里插入图片描述
代码刨析

  1. 我们之所以在两个数的时候能够赋值,是因为this指针在函数内部就对d2进行了修改。
  2. 在连续赋值的时候,我们该重载函数返回的是void类型,相当于我们在对d1赋值的时候是传递了一个void类型的数据过去,void类型又怎么可以赋值呢?因此我们要想实现连续赋值这里肯定是不能用void作为返回类型。

在这里插入图片描述
那么我们又如何解决连续赋值存在的问题呢?
3. 在前面我们知道了是返回值的问题,那么我们就可以通过对返回值的修改来帮助我们解决
4. 返回什么呢?这里我们可以通过返回this*,此时这里的返回值等价于返回了d2这个对象,因此可以通过返回引用来解决返回值的问题

class Date
{
public:Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << "year = " << this->_year << " month = " << this->_month << " day = " << this->_day << endl;}Date& operator=(const Date& s1){_year = s1._year;_month = s1._month;_day = s1._day;return *this;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2003,9,22);Date d2(2002,9,26);Date d3(0, 0, 0);cout << "重载前" << endl;d1.Print();d2.Print();d3.Print();d1 = d2 = d3;cout << "重载后" << endl;d1.Print();d2.Print();d3.Print();   return 0;
}

在这里插入图片描述


显示重载

显示赋值操作符重载:用的比较少这里作者就偷懒提一下

class MyClass {
public:MyClass& operator=(const MyClass& other) {//显示重载// 在这里实现赋值操作return *this;}
};int main() {MyClass obj1;MyClass obj2;obj2 = obj1; // 调用赋值操作符重载return 0;
}

注意事项

在C++中,运算符重载是一种强大的特性,它可以让我们自定义类类型的行为,使其像内置类型一样使用运算符。然而,运算符重载也需要遵循一些注意事项,以确保正确和安全地使用。

以下是运算符重载的一些注意事项:

  1. 只能重载已存在的运算符:C++只允许重载已存在的运算符,而不允许创建新的运算符。例如,可以重载"+", “-”, "*“等运算符,但不能重载”%%“或”**"等新的运算符。

  2. 不改变运算符的优先级:运算符重载不会改变运算符的优先级和结合性。例如,重载"+"运算符不会改变它的加法操作的优先级和结合性。

  3. 重载运算符需要至少一个操作数是用户定义的类型:为了重载运算符,至少需要一个操作数是用户定义的类型(自定义类),因此重载的运算符不能用于内置类型的操作。

  4. 通常情况下,重载运算符应该作为类的成员函数:通常情况下,应该将运算符重载函数声明为类的成员函数。这样可以使其在类的对象上直接调用,并享受到类的私有成员的访问权限。然而,也可以将运算符重载函数声明为友元函数,以便访问类的私有成员。

  5. 一些运算符只能重载为成员函数:一些运算符(例如赋值运算符和下标运算符)只能作为类的成员函数进行重载。这是因为它们对操作数的顺序有特定的要求,只能将类的对象作为左操作数。

  6. 谨慎使用运算符重载:运算符重载是一种很强大的特性,但也容易被滥用。在重载运算符时,要确保其行为符合直觉,不会给其他开发者带来困惑。建议只在有必要时才使用运算符重载,避免滥用。

  7. 重载运算符的返回类型应该符合预期:重载运算符的返回类型应该符合预期的语义和行为。例如,重载"+="运算符时,返回的是左操作数的引用,以实现链式赋值的语法。

需要注意的是,虽然运算符重载可以更灵活地使用类对象,但也需要谨慎使用,以避免混淆和错误的行为。在重载运算符时,应该遵循一些通用的原则和最佳实践,确保代码的可读性、可维护性和安全性。


好啦,今天的内容就到这里啦,下期内容预告类和对象(四)日期类的实现


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


🌏🗺️ 这里祝各位寒假愉快 💞💞

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

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

相关文章

Java并发基础:FutureTask全面解析!

内容概要 FutureTask结合了Future和Runnable接口&#xff0c;它能够异步执行任务&#xff0c;提高程序响应性&#xff0c;可以获取任务执行结果&#xff0c;并且支持任务取消机制&#xff0c;提高了灵活性&#xff0c;同时&#xff0c;它简化了并发编程&#xff0c;使多线程开…

【Linux系统 02】Shell脚本

目录 一、Shell概述 二、输入输出 三、分支控制 1. 表达式 2. if 分支 3. case 分支 四、循环控制 1. for 循环 2. while 循环 3. select 循环 五、函数 一、Shell概述 Shell是Linux系统连接用户和操作系统的外壳程序&#xff0c;将用户的输入和请求选择性传递给操…

Java中Object类常用的12个方法

前言 Java 中的 Object 方法在面试中是一个非常高频的点&#xff0c;毕竟 Object 是所有类的“老祖宗”。Java 中所有的类都有一个共同的祖先 Object 类&#xff0c;子类都会继承所有 Object 类中的 public 方法。 先看下 Object 的类结构&#xff1a; 1. getClass 方法 pub…

「悬浮捷径SoftCircle」安卓平台的hao123,一键打开万物

罗老师的onestep一步发布之前, 终端的打开形式还拘泥于桌面和负一屏 这种方式够简洁,但缺点明显: 1.入口单一性:只能在app首页和各种扫一扫之间选择和切换 2.操作复杂:入口切换需要频繁的进入退出桌面,步骤过于繁杂 以下是悬浮捷径SoftCircle的解决方式 1.入口的丰富性: 安卓平…

如何在飞凌嵌入式T113-i开发板的Buildroot中移植MQTT协议?

在实际的项目开发中&#xff0c;工程师朋友们可能会需要在文件系统中移植一些工具或协议&#xff0c;那么该如何进行移植操作呢&#xff1f; 我们可以通过添加package包配置的方式在OK113i-S开发板的Buildroot中移植新功能。本篇文章&#xff0c;小编就以在Buildroot移植MQTT协…

关于Django部署

首先了解一下开发环境服务器跟生产环境服务器有何不同。 一、我们通过 python manage.py runserver 启动开发环境服务器&#xff0c;这条命令背后做了哪些事情&#xff1f; 1、首先加载Django项目的设置&#xff08;settings&#xff09; 2、检查数据库迁移&#xff0c;确保数…

Leetcode92:反转链表II(区间反转链表)

一、题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a…

Multisim14.0仿真(五十一)基于LM555定时器的分频器设计

一、1KHz脉冲设置&#xff1a; 二、555脉冲电路&#xff1a; 三、仿真电路&#xff1a; 四、运行仿真&#xff1a;

Day 1. 学习linux高级编程之Shell命令和IO

1.C语言基础 现阶段学习安排 2.IO编程 多任务编程&#xff08;进程、线程&#xff09; 网络编程 数据库编程 3.数据结构 linux软件编程 1.linux&#xff1a; 操作系统&#xff1a;linux其实是操作系统的内核 系统调用&#xff1a;linux内核的函数接口 操作流程&#xff…

Unity类银河恶魔城学习记录1-10 PlayerWallJump源代码 P37

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Player.cs using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; u…

海外YouTube视频点赞刷单悬赏任务投资理财源码/tiktok国际版刷单理财

测试环境&#xff1a;Linux系统CentOS7.6、宝塔、PHP7.3、MySQL5.7&#xff0c;根目录public&#xff0c;伪静态Laravel5&#xff0c;开启SSL证书 前端&#xff1a;修改网站的默认文档 index.html 为第一个&#xff0c; index.php 改成第二个 &#xff0c;或者前端访问 index.…

OJ_整数奇偶排序

题干 c实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<algorithm> using namespace std;//compare函数不交换返回true bool compare(int a, int b) {//1.a奇数&#xff0c;b偶数&#xff0c;不交换//2.a奇数&#xff0c;b奇数&#xff0c;a比b…

C语言实现跳表(附源码)

最近在刷一些链表的题目&#xff0c;在leetcode上有一道设计跳表的题目&#xff0c;也是通过查阅各种资料&#xff0c;自己实现出来&#xff0c;感觉这是种很神奇的数据结构。 一.简介 跳表与红黑树&#xff0c;AVL树等&#xff0c;都是一种有序集合&#xff0c;那既然是有序…

Prompt Engneering(提示词工程)

大模型的目标是理解和生成人类语言。给定一些词语&#xff0c;语言模型可以预测下一个词语可能是什么&#xff0c;或者给定的一些词语生层对应内容。 那么如何引导它们产生期望的输出&#xff0c;或者说如何提问&#xff0c;就成为了一个关键的问题。这就引入了一个重要的概念…

QStandardItemModel与QTableView里如何设置复选框居中

笔者为这个问题思索了不少时间&#xff0c;这个问题就是c qt里创建了一个QStandardItemModel设置了表格的表头&#xff0c;往表格填充数据时&#xff0c;数据的复选框左对齐&#xff0c;想要设置复选框居中对齐&#xff0c;不知道如何处理&#xff0c;这里给出代码与运行效果&a…

用Python画一条祥龙,祝您新年龙腾万里

用Python画一条祥龙&#xff0c;祝您新年龙腾万里 龙年到了&#xff0c;祝大家新年龙行龘龘&#xff0c;龙腾万里&#xff01; 从2021年开始&#xff0c;我每年都用Python画一幅当年生肖的图。 用Python标准库turtle画一头金牛&#xff0c;祝您新年牛气冲天&#xff01; 用P…

vscode 括号 python函数括号补全

解决方法 在setting.json中添加 “python.analysis.completeFunctionParens”: true 打开设置&#xff1b; 点击图中按钮打开setting.json文件 添加 “python.analysis.completeFunctionParens”: true

apipost 简单的性能压测总结

1、简单的使用机型牌评估 1&#xff09;jdk默认256M给100用&#xff0c;推荐给1000人同时用JVM 堆栈建议2G~4G&#xff08;目前定了机型4核8G内存 2T磁盘做radio0存储&#xff09;&#xff1b; 2&#xff09;数据库配置文件写了占了2G内存&#xff08;my.cnf文件&#xff09…

Python算法100例-1.3 牛顿迭代法求方程根

完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1&#xff0e;问题描述 编写用牛顿迭代法求方程根的函数。方程为 a x 3 b x 2 c x d 0 ax^3bx^2cxd0 ax3bx2cxd0&#xff0c;系数a、b、c、d由主函数输入&#xff0c;求x在1附近的一个实根。求出根后&…

详解SkyWalking前端监控的性能指标

SkyWalking 从8.2.0版本开始支持对前端浏览器端的性能进行监控&#xff0c;不仅可以像以前一样监控浏览器发送给后端服务的与请求&#xff0c;还能看到前端的渲染速度、错误日志等信息——这些信息是获取最终用户体验的最有效指标。实现的方式是引入skywalking-client-js库&…