C++---运算符重载

news2024/11/17 15:26:58

在这里插入图片描述

运算符重载介绍

在类中重新定义运算符,赋予运算符新的功能以适应类的运算,就称为运算符重载。
运算符重载是一种形式的C++多态,它使得对象操作更直观,本质上也是属于函数重载。
实际上,我们已经在不知不觉之中使用了运算符重载。例如,加法运算符“+”可以对整数相加、也可以对string对象相加,如5+8; string s1=“abc”;string s2=“xyz”; s1+s2;这是因为C++已经对string类重载了“+”运算符。
又例如,C++对“<<”和“>>”进行了重载,用户在不同的场景下使用它们,作用是不同的。
对于位运算而言,“<<”运算符是左移运算符,“>>”运算符是右移运算符。
“<<”运算符在输出操作中与流对象cout配合使用,是流插入运算符;“>>”运算符在输入操作中与流对象cin配合使用,是流提取运算符。
对于自定义的新类型,需要对使用的运算符进行重新定义即运算符重载。如果某个运算符重载了,那么在使用该运算符时,系统会自动调用。
运算符重载格式如下:

返回值类型 operator 运算符(参数);//注意 operator关键字必须写

其中,operator 是 C++的关键字,专门用于定义运算符重载函数。

例如,operator +(),表示:重载+运算符,operator (),表示:重载运算符。
假设有一个Student类,并为它定义了一个operator +()成员函数,以重载+运算符,如果有Student的对象s1,s2,s3。便可以编写这样的代码。

s1 = s2+s3; //1 直接使用重载运算符

编译器发现,操作数是Student类对象,则使用相应的运算符函数替换上述代码。

s1 = s2.operator+(s3);//2 函数表示法,不如上面的简洁

当然,最重要的是可以使用简便的+运算符表示(如1),而不必使用笨拙的函数表示法(如2)。

计算时间

如果你今天上午编程花了2小时35分钟,下午又花了2小时40分钟,则总共花了多少时间呢?
现在采用一个Time类来处理。

class Time
{
private:
	int hours;//小时
	int minutes;//分钟
public:
	Time(int h=0,int m=0):hours(h),minutes(m)//构造函数
    {}
	Time operator +(const Time& t)const;//重载+,注意返回值不是引用
	void show() const;
};

Time Time::operator +(const Time& t) const//返回的是临时变量,不能写引用
{
	return Time(hours + t.hours + (minutes + t.minutes) / 60, (minutes + t.minutes)% 60);
}

void Time::show() const
{
	cout << hours << "小时," << minutes << "分钟" << endl;
}

int main()
{
	Time t1 = { 2,35};
	Time t2 = { 2,40 };
	Time t3 = t1 + t2;
	t3.show();

	return 0;
}

重载的限制

1.重载后的运算符至少有一个操作数是用户定义的类型。这是防止你为内置类型重载运算符,你不能将减法(-)重载为两个整数的和。
2.不能改变运算符的操作数和优先级。例如不能将取余(%)重载成一元运算符。
3.不能创建新运算符。例如不能定义operator **()函数来表示指数。
4.不能重载下面的运算符(了解,不重要)。

sizeof : sizeof运算符 (可以是类型,不具备重载要求)

. : 成员运算符 (保证访问成员的功能不被改变)

.*: 成员指针运算符 (保证访问成员的功能不被改变)

:: : 作用域解析运算符 (类型,不具备重载要求)

? : : 条件运算符 (语义无法保证)

typeid : 获取类型信息运算符 (类型,不具备重载要求)

const_cast : 强制类转换运算符 (类型,不具备重载要求)

dynamic_cast : 强制类型转换运算符 (类型,不具备重载要求)

reinterpret_cast : 强制类型转换运算符 (类型,不具备重载要求)

static_cast : 强制类型转换运算符 (类型,不具备重载要求)

5.上表中的大多数运算符都可以通过成员或非成员函数进行重载,但下面的运算符只能通过成员函数进行重载(左边必须是类对象)。

= : 赋值运算符

():函数调用运算符

[]:下标运算符

->:通过指针访问类成员的运算符
假如运行 [ ]重载为非成员函数,那么可能出现下面的程序

Time& operator[](int n, Time& t)
{
    //...一些操作
    return c;
}

int main()
{
    Time t(1, 10);
    6[t]; //会出现这种奇怪的写法

    return 0;
}

6.为了区分++,–的前置和后置。C++标准做了一个约定,在后置运算符的参数类别中增加一个int。例如

返回值 operator ++();//前置++
返回值 operator ++(int);//后置++,这个int没有实际意义,仅仅用来说明它是后置运算符
返回值 operator --();//前置--
返回值 operator --(int);//后置--,这个int没有实际意义,仅仅用来说明它是后置运算符

其它运算符重载

还有一些其它操作对于Time来说是有意义的。例如,将两个时间相减或时间乘以一个因子,这需要重载减法和乘法运算符。


class Time
{
private:
    int hours;//小时
    int minutes;//分钟
public:
    Time(int h=0,int m=0):hours(h),minutes(m)//构造函数
    {}
    Time operator +(const Time& t)const;//重载 +,注意返回值不是引用
    Time operator -(const Time& t)const;//重载 -
    Time operator *(double n)const;//重载 *
    void show() const;
};

Time Time::operator +(const Time& t) const//返回的是临时变量,不能使用引用
{
    return Time(hours + t.hours + (minutes + t.minutes) / 60, (minutes + t.minutes) % 60);
}

Time Time::operator -(const Time& t)const
{
    int minu1 = hours * 60 + minutes;//把this的时间转为分钟
    int minu2 = t.hours * 60 + t.minutes;//把t的时间转为分钟

    return Time((minu1 - minu2) / 60, (minu1 - minu2) % 60);
}
Time Time::operator *(double n)const
{
    int minu = hours * 60 + minutes;//把this的时间转为分钟
    minu = int( minu * n );//分钟取整
    return Time(minu/60,minu%60);
}

void Time::show() const
{
    cout << hours << "小时," << minutes << "分钟" << endl;
}

int main()
{
    Time t1 = { 2,35 };
    Time t2 = { 2,40 };
    Time t3 = t1 + t2; //测试+
    Time t4 = t2 - t1;//测试-
    Time t5 = t1 * 1.5;//测试*
    t3.show();
    t4.show();
    t5.show();

    return 0;
}

注意:运算符重载应该反应操作的本质,如果使用运算符的重载反而让程序难以理解,就不要使用,直接定义函数更好。
运算符通过类成员函数进行重载,那么第一个操作数必须是类对象本身.
有时第一个操作数可能并不是类对象。例如 3*t1;

Time t6 = 3 * t1;//错误
t6.show();

非成员函数重载

为了解决这个问题,需要实现一个非成员函数的*运算符重载,函数声明如下:

Time operator *(double m, const Time& t);//这不是类成员函数,在类外声明(没有Time::)

这又带来另外一个问题,由于上面的函数不是类的成员函数,那么它是不能直接访问Time的私有成员数据的,有两个办法可以解决,1.在Time类中提供访问获取私有数据的接口方法(下面代码中的getHours和getMinutes);2.把上面的函数设为Time的友元函数。下面演示方法1


class Time
{
private:
    int hours;//小时
    int minutes;//分钟
public:
    Time(int h=0,int m=0);
    Time operator +(const Time& t)const;//重载+,注意返回值不是引用
    Time operator -(const Time& t)const;
    Time operator *(double n)const;
    void show() const;
    int getHours()const //获取小时值
    {
        return hours;
    }
    int getMinutes()const//获取分钟值
    {
        return minutes;
    }
};

Time::Time(int h, int m)
{
    hours = h;
    minutes = m;
}

Time Time::operator +(const Time& t) const//返回的是临时变量,不能写引用
{
    return Time(hours + t.hours + (minutes + t.minutes) / 60, (minutes + t.minutes) % 60);
}

Time Time::operator -(const Time& t)const
{
    int minu1 = hours * 60 + minutes;//把this的时间转为分钟
    int minu2 = t.hours * 60 + t.minutes;//把t的时间转为分钟

    return Time((minu1 - minu2) / 60, (minu1 - minu2) % 60);
}
Time Time::operator *(double n)const
{
    int minu = hours * 60 + minutes;//把this的时间转为分钟
    minu = int( minu * n );//分钟取整
    return Time(minu/60,minu%60);
}

void Time::show() const
{
    cout << hours << "小时," << minutes << "分钟" << endl;
}

Time operator *(double m, const Time& t)
{
    int minus = int(m*(t.getHours() * 60 + t.getMinutes()));

    return Time(minus/60,minus%60);
}

int main()
{
    Time t1 = {2,35};
    Time t2 = { 2,40 };
    Time t3 = t1 + t2;
    Time t4 = t2 - t1;
    Time t5 = t1 * 1.5;
    t3.show();
    t4.show();
    t5.show();

    Time t6 = 3 * t1;//数字写在前
    t6.show();

    return 0;
}

本篇完!

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

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

相关文章

ElasticSearch操作之重置密码脚本

ElasticSearch操作之重置密码脚本 #!/bin/bash # 使用样例 ./ES密码重置.sh 旧密码 新密码# 输入旧密码 es_old_password$1# 设置新的密码变量 es_password$2# 正确响应 es_reponse{"acknowledged":true}# 检查Elasticsearch是否在运行 if pgrep -f elasticsearch &g…

用WPS将多张图片生成一个pdf文档,注意参数设置

目录 1 新建一个docx格式的文档 2 向文档中插入图片 3 设置页边距 4 设置图片大小 5 导出为pdf格式 需要把十几张图片合并为一个pdf文件&#xff0c;本以为很简单&#xff0c;迅速从网上找到两个号称免费的在线工具&#xff0c;结果浪费了好几分钟时间&#xff0c;发现需要…

电影《朝云暮雨》观后感

上周看了电影《朝云暮雨》&#xff0c;看完之后&#xff0c;感觉自己整个人都不太好了&#xff0c;也不是说电影太差&#xff0c;只是觉得电影没有传达正能量&#xff0c;让人很不舒服。 &#xff08;1&#xff09;演技在线 对于著名的演员“范伟”&#xff0c;或者说&#x…

邮件系统数据面临的安全问题及解决方法

随着电子邮件的普及&#xff0c;邮件系统已成为企业、学校、个人等用户之间进行信息交流的重要工具。然而&#xff0c;随着数据量的增加和用户对邮件系统的依赖&#xff0c;邮件系统数据安全问题也逐渐凸显。下面U-Mail技术张工就给大家讲解一下邮件系统数据面临的主要安全问题…

权限维持--windows

隐藏文件 ①文件属性隐藏 如何排查&#xff1a; 使用dir命令无法看到有特殊属性的文件需使用/a ②真隐藏 相当于给原本的文件增加系统文件属性、存档文件属性、只读文集属性、隐藏文件属性 如何排查&#xff1a; 取消受保护的操作系统文件 ③利用ADS隐藏 使用数据流 echo &…

远动通讯屏的原理和应用

远动通讯屏的原理和应用 远动通讯屏&#xff0c;是一种集显示和远程控制于一体的智能化控制设备。它可以通过网络、通信线路等方式实现与远程设备的通讯和交互&#xff0c;从而实现远程监控和控制。 远动通讯屏实现远程控制的核心原理是基于PLC&#xff08;Programmable Logic …

SpringCloud Alibaba Nacos分类配置--多方案配置隔离

文章目录 Nacos 分类配置(实现配置隔离)1.DataID 方案需求分析/图解配置实现测试 2.Group 方案需求分析/图解配置实现修改application.yml修改bootstrap.yml测试 3.Namespace 方案需求分析/图解配置实现修改application.yml修改bootstrap.yml测试 Namespace/Group/Data ID 关系…

Mac下QT开发环境搭建详细教程

QT Qt是一个跨平台的C应用程序框架&#xff0c;用于开发具有图形用户界面&#xff08;GUI&#xff09;的应用程序&#xff0c;同时也可用于开发非GUI程序&#xff0c;比如控制台工具和服务器。Qt是设计成通用、可移植和高效的&#xff0c;它广泛应用于全球的企业和开发者社区中…

【译】MySQL 组复制 - 部分网络故障对性能的影响

原文地址&#xff1a;MySQL Group Replication – Partial Network Failure Performance Impact 在这个由两部分组成的博客系列中&#xff0c;我想介绍一些使用组复制的故障转移场景。在第一部分中&#xff0c;我将讨论我在撰写这些文章时发现的一种有趣的行为和性能下降。在第…

Kubernetes中 Requests 和 Limits 的初步理解

1 灵魂拷问 我们在使用 Kubernetes 时是否遇到以下情况&#xff1a; 你会不会部署负载的时候将 CPU requests/limits 设置得过低或过高&#xff1f;你会不会部署负载的时候将 内存 requests/limits 设置得过低或过高&#xff1f;又或者你根本不设置 requests/limits&#xff…

【Linux网络编程】IO多种转接之Reactor

Reactor 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 基于上一篇epoll的学习&#xff0c;现在我们也知道epoll的工作模式有两种&#xff0c…

前端菜鸡,对于35+程序员失业这个事有点麻了

“经常看到30岁程序员失业的新闻&#xff0c;说实话&#xff0c;有点麻。目前程序员供求关系并未失衡&#xff0c;哪怕是最基础的前端或者后台、甚至事务型的岗位也是足够的。 事实上&#xff0c;现在一个开出的岗位要找到一位尽职尽责能顺利完成工作的程序员并不是一件那么容…

石油化工巡检机器人:应对挑战的创新力量

在石油化工领域&#xff0c;安全始终是高悬的达摩克利斯之剑。人工巡检面临诸多痛点&#xff0c;如高危环境对人身安全的巨大威胁&#xff0c;复杂工况下难以做到全面细致监测&#xff0c;对有害气体检测存在滞后性&#xff0c;还有恶劣天气对巡检工作的严重干扰。而这些痛点&a…

[LLM-Agent]万字长文深度解析规划框架:HuggingGPT

HuggingGPT是一个结合了ChatGPT和Hugging Face平台上的各种专家模型&#xff0c;以解决复杂的AI任务&#xff0c;可以认为他是一种结合任务规划和工具调用两种Agent工作流的框架。它的工作流程主要分为以下几个步骤&#xff1a; 任务规划&#xff1a;使用ChatGPT分析用户的请求…

【linux】新增磁盘的使用

查看硬盘和分区信息 【Linux】lsblk 命令使用-CSDN博客 lsblk 根据您提供的lsblk命令输出&#xff0c;我们可以看到系统中的块设备及其分区信息。以下是对每个设备的解释&#xff1a; vda&#xff1a;这是一个大小为40G的磁盘设备。 vda1&#xff1a;这是vda磁盘的第一个分区…

unidbg入门笔记

一、unidbg 介绍 unidbg 是凯神 在 2019 年初开源的一个轻量级模拟器&#xff0c;一个基于Java的跨平台解密引擎&#xff0c;专门用于动态分析和逆向工程应用程序。它可以模拟不同CPU架构、操作系统和指令集&#xff0c;从而使用户能够在一个统一的环境中分析各种不同类型的二…

利用Python去除PDF水印

摘要 本文介绍了如何使用 Python 中的 PyMuPDF 和 OpenCV 库来从 PDF 文件中移除水印&#xff0c;并将每个页面保存为图像文件的方法。我们将深入探讨代码背后的工作原理&#xff0c;并提供一个简单的使用示例。 导言 简介&#xff1a;水印在许多 PDF 文件中都很常见&#x…

用 vue3 + phaser 实现经典小游戏:飞机大战

本文字数&#xff1a;7539字 预计阅读时间&#xff1a;30分钟 01 前言 说起小游戏&#xff0c;最经典的莫过于飞机大战了&#xff0c;相信很多同学都玩过。今天我们也来试试开发个有趣的小游戏吧&#xff01;我们将从零开始&#xff0c;看看怎样一步步实现一个H5版的飞机大战&a…

MyBatis从入门到“入土“

&#x1f495;喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#xff01;&#x1f495;(●◡●) 目录 一、Mybatis为何物&#xff1f;&#x1f44c; 二、快速入门&#x1f923; 1、新建项目&#x1f60a; 2、数据库建表&#x1f60a; 3、导入依赖的jar包&#x1f60a;…

【高级数据结构】B树

B树 一、概念性问题1、前置知识&#xff1a;常见搜索结构2、常规使用数据结构缺陷问题3、B树概念4、存放数量分析 二、代码实现逻辑1、结点定义和基本框架2、Find查找函数&#xff08;1&#xff09;思想&#xff08;2&#xff09;代码实现 3、InsertKey插入关键字函数--InsertK…