『C++成长记』运算符重载

🔥博客主页:小王又困了

📚系列专栏:C++

🌟人之为学,不日近则日退

❤️感谢大家点赞👍收藏⭐评论✍️

目录

一、运算符重载

📒1.1两个日期大小的比较

📒1.2运算符重载的引入

📒1.3将运算符重载函数写成成员函数

二、赋值运算符重载


一、运算符重载

int main()
{
    int x = 1, y = 2;
    bool x > y;

    Date d1;
    Date d2(2023, 11, 20);
    bool d1 > d2;//不支持
    return 0;
}

     我们比较两个对象的大小,对于内置类型,可以直接使用运算符,内置类型都是简单类型,语言自己定义的,编译器直接转换成指令;对于自定义类型,编译器不知道它的行为,所以不支持直接使用运算符。那自定义类型该如何比较大小呢?我们以日期类为例。

📒1.1两个日期大小的比较

class Date
{
public:
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
private:
    int _year;//年
    int _month;//月
    int _day;//日
};

int main()
{
	Date d1(2023, 5, 21);
	Date d2(2023, 11, 20);
	return 0;
}

定义了d1d2两个对象,我们可以通过函数比较两个日期的大小,如下:

//以大于为例
bool Greater(const Date& x, const Date& y)
{
    if (x._year > y._year)
    {
        return true;
    }
    else if (x._year == y._year && x._month > y._month)
    {
        return true;
    }
    else if (x._year == y._year && x._month == y._month && x._day > y._day)
    {
        return true;
    }
    
    return false;
}

int main()
{
    Date d1(2023, 5, 21);
    Date d2(2023, 11, 20);
    cout << Greater(d1, d2) << endl;
    return 0;
}

但这里有一个问题,Greater函数是定义在类外的,日期类的成员变量是私有的,所以在类外是无法访问到的,想要实现比较的功能就要将成员变量设为public公有,这样代码是不安全的。

📒1.2运算符重载的引入

     有些人给函数命名时并不规范,例如:Compare1Compare2等。我们不知道这个函数实现的是什么功能,只有看过代码才知道,这样十分麻烦。C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

  • 函数名字:关键字operator后面接需要重载的运算符符号
  • 函数原型:返回值类型 operator操作符(参数列表)
//以大于为例
bool operator>(const Date& x, const Date& y)
{
    if (x._year > y._year)
    {
        return true;
    }
    else if (x._year == y._year && x._month > y._month)
    {
        return true;
    }
    else if (x._year == y._year && x._month == y._month && x._day > y._day)
    {
        return true;
    }
    
    return false;
}

int main()
{
    Date d1(2023, 5, 21);
    Date d2(2023, 11, 20);
    cout << (d1 > d2) << endl;
    return 0;
}

注意:流插入的优先级高,我们要先比较大小,所以d1>d2要加括号。

📒1.3将运算符重载函数写成成员函数

     为了解决上面的私有成员变量在类外面无法访问的问题,可以把运算符重载函数写成类的成员函数或者友元,这样就能访问到私有的成员变量,但是友元一般不建议使用,因为友元会破坏封装。

class Date
{
public:
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    bool operator>(const Date& y)
    {
        if (year > y._year)
        {
            return true;
        }
        else if (year == y._year && month > y._month)
        {
            return true;
        }
        else if (year == y._year && month == y._month && day > y._day)
        {
            return true;
        }

        return false;
    }

private:
    int _year;//年
    int _month;//月
    int _day;//日
};

运算符重载有一个规定,运算符要与参数个数匹配, 是双目操作符,但上面的代码为什么只传递了一个参数,这是因为成员函数中都有一个隐藏的this,所以形参就只需要一个。

int main()
{
    d1 > d2;
    d1.operator>(&d1, d2);//显示调用
    return 0;
}

d1 > d2会转化为 d1.operator>(&d1, d2)

运算符重载有意义就可以实现,没有意义就不要实现。例如:日期+日期就没有意义,但日期-日期就有意义。

📝注意:

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

二、赋值运算符重载

📝区分赋值运算符重载和拷贝构造 

Date d1(2020, 5, 21);
Date d2(2023, 6, 21);
d1 = d2;//需要调用赋值运算符重载
Date d3(d1);//调用拷贝构造

要区分赋值运算符重载拷贝构造,前者是针对两个已存在的对象,将一个对象的值,赋值给另一个,而后者是用一个已存在的对象去初始化创建一个新对象。

赋值运算符重载格式:

  • 参数类型const T&(T是类型),传递引用可以提高传参效率
  • 返回值类型T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this :要复合连续赋值的含义
Date& operator=(const Data& d)
{
    if (this != &d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
	}
    return *this;//出了作用域*this还在,所以可以用引用返回
}

📝赋值运算符只能重载成类的成员函数不能重载成全局函数 

// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
    if (&left != &right)
    {
        left._year = right._year;
        left._month = right._month;
        left._day = right._day;
    }
    return left;
}

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

📝编译器生成的默认赋值运算符重载做了什么

     用户没有显式实现时,编译器生成的默认赋值运算符重载,对内置类型的成员变量是以值的方式逐字节进行拷贝(浅拷贝),对自定义类型的成员变量,调用其对应类的赋值运算符重载。


🎁结语: 

     本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Navicat for Mysql怎么执行创建表的脚本

Navicat for Mysql怎么执行创建表的脚本 Navicat 怎么执行sql文件 Navicat 执行创建表语句 Navicat 执行sql语句 Navicat 怎么创建表语句 1、打开Navicat数据库管理工具&#xff1b; 2、点击菜单栏上的“工具”&#xff0c;选择“命令列界面”&#xff1b; 打开了命令列界面…

多肉植物,预计到2025我国市场规模将达到140亿元人民币

多肉植物是一种新兴的盆栽植物&#xff0c;由于造型各异、易于养殖、低维护难度等优点&#xff0c;在全球市场和中国市场受到了越来越多消费者的追捧。全球市场分析 从全球市场来看&#xff0c;多肉植物市场规模正在逐步扩大。各种形态各异的多肉植物受到消费者的喜爱&#xff…

魔术表演Scratch-第14届蓝桥杯Scratch省赛真题第1题

1.魔术表演&#xff08;20分&#xff09; 评判标准&#xff1a; 4分&#xff1a;满足"具体要求"中的1&#xff09;&#xff1b; 8分&#xff1a;满足"具体要求"中的2&#xff09;&#xff1b; 8分&#xff0c;满足"具体要求"中的3&#xff09…

ArrayList集合综合练习

文章目录 题目1训练目标训练提示训练步骤参考答案 题目2训练目标训练提示参考方案训练步骤参考答案 题目3训练目标训练提示参考方案训练步骤参考答案 题目4&#xff08;综合&#xff09;训练目标训练提示参考方案训练步骤参考答案 题目1 现有如下字符串元素&#xff1a;[“aaa…

ocrmypdf_pdf识别

安装 安装说明 https://ocrmypdf.readthedocs.io/en/latest/installation.html#native-windows提到需要的软件&#xff1a; Python 3.7 (64-bit) or later Tesseract 4.0 or later Ghostscript 9.50 or later 安装 ocrmypdf pip install ocrmypdf 添加语言包 https://oc…

科研+临床观摩|牙科医生公派美国从事访问学者交流

很多临床医学专业的访问学者希望在访学从事科研的同时&#xff0c;能到医院进行临床观摩。对于这些申请者的要求&#xff0c;我们会尽量满足。本案例中的T医生&#xff0c;口语较弱&#xff0c;担心英语面试&#xff0c;最终我们为其取得了田纳西大学健康科学中心的邀请函&…

【QT】QStandardItemModel类的应用介绍

目录 1 概述 2 常用方法 3 QStandardItemModel的使用 3.1 界面设计与主窗口类定义 3.2 系统初始化 3.3 从文本文件导入数据 3.4 数据修改 3.5 单元格格式设置 3.6 数据另存为文件 1 概述 QStandardItemModel是标准的以项数据&#xff08;itemdata&#xff09;为基础的…

【Linux】set命令使用

set命令 设置所使用shell的执行方式&#xff0c;可依照不同的需求来做设置。 语法 set [参数]选项及作用 执行令 &#xff1a; man set 执行命令结果 参数 -a  标示已修改的变量&#xff0c;以供输出至环境变量。-b  使被中止的后台程序立刻回报执行状态。-C  转向所…

Android开发中“真正”的仓库模式

原文地址&#xff1a;https://proandroiddev.com/the-real-repository-pattern-in-android-efba8662b754原文发表日期&#xff1a;2019.9.5作者&#xff1a;Denis Brandi翻译&#xff1a;tommwq翻译日期&#xff1a;2024.1.3 Figure 1: 仓库模式 多年来我见过很多仓库模式的实…

liunx操作系统基础及进阶

一、基础入门 1、Linux系统简介 什么是Liunx&#xff1f; Linux在设计之初&#xff0c;是一个基于POSIX的多用户、多任务并且支持多线程和多CPU的操作系统&#xff0c;它是由世界各地成千上万的程序员设计和开发实现&#xff1b; 在当今社会&#xff0c;Linux 系统主要被应…

史上最细,13年老鸟总结-性能测试7大关键点,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试环境的鉴定…

MQTT基础下载使用

1.下载MQTT(MQTT官网) 下载完后在bin目录下启动cmd 控制台输入emqx start&#xff0c;注意&#xff0c;此时控制台是没有反应的&#xff0c;就回你个D&#xff1a;\EMQX。其实已经打开了。 打开桌面上的MQTTX 并新建连接 这是测试的数据 我订阅了一个test1的订阅 并且我发布…

跑步中位数

title: 跑步中位数 date: 2024-01-04 15:47:51 tags: 对顶堆 catefories: 算法进阶指南 题目大意 解题思路 动态维护中位数问题。可以建立两个二叉堆&#xff0c;一个大顶堆一个小顶堆&#xff0c;在依次读入整数序列的过程中&#xff0c;设当前序列长度为 M M M,我们始终保持…

软件测试之冒烟测试

一、什么是冒烟测试 这一术语源自硬件行业。对一个硬件或硬件组件进行更改或修复后&#xff0c;直接给设备加电。如果没有冒烟&#xff0c;则该组件就通过了测试。在软件中&#xff0c;“冒烟测试”这一术语描述的是在将代码更改嵌入到产品的源树中之前对这些更改进行验证的过…

通过聚道云软件连接器实现销帮帮软件与i人事软件的智能对接

客户介绍 某软件行业公司是一家专业从事软件技术服务、软件开发、应用解决方案、业务流程优化、专业服务的高科技企业。公司拥有一支经验丰富、技术精湛的服务团队&#xff0c;具备多年的软件开发和应用解决方案经验。他们不断追求技术的创新和进步&#xff0c;以满足客户不断…

CCF录用率怎么看?如何挑选合适的会议

写在前面 写此文是因为有同学问我如何确定自己能投稿的会议。首先&#xff0c;不建议直接用他人汇总好的数据&#xff08;截稿时间和录用率&#xff09;&#xff0c;如果遇到更新不及时的很有可能耽误自己的工作。 平常&#xff0c;我都会自己收集预计投稿时间的会议信息&…

phpstudy_pro 关于多版本php的问题

我在phpstudy中安装了多个PHP版本 我希望不同的网站可以对应不同的PHP版本&#xff0c;则在nginx配置文件中需要知道不同的PHP版本的监听端口是多少&#xff0c;如下图所示 然而找遍了php.ini配置&#xff0c;并未对listen进行设置&#xff0c;好奇是怎么实现不同的PHP监听不同…

炼石白小勇:免改造安全技术实现数据监管合规与有序流通

2023年9月15日&#xff0c;2023世界计算大会在湖南长沙开幕。在开幕论坛上&#xff0c;全国政协副主席、民建中央常务副主席秦博勇指出&#xff0c;当今世界正在经历一场更大范围、更深层次的科技革命和产业变革。湖南省委书记沈晓明在致辞中说&#xff0c;湖南将推动计算产业开…

python的课后练习总结4(for循环)

1&#xff0c;for循环 for 临时变量 in 序列: 重复执行的代码1 重复执行的代码2 ........... 遍历序列 字符串 我是中国人 列表 [‘星期一,星期二,星期三,星期四] 元组 (‘星期一,星期二,星期三,星期四&#xff09; 一&#xff0c;break 终止循环 二&#xff0c;con…

VS Code技巧汇总

VS Code技巧汇总 前言设置快捷键插件汇总环境搭建HTMLC/CPython 远程SSH连接被控端准备安装扩展配置SSH创建SSH连接打开终端窗口通过公钥连接SSH 前言 本文介绍VS Code的使用技巧&#xff0c;内容包含设置、快捷键、插件汇总、环境搭建、远程SSH连接、等等。 设置 中文界面 …