c++ - 运算符重载

文章目录

    • 一、运算符重载的关键字和注意点
    • 二、重载`=` 运算符
    • 三、重载`+` 运算符
    • 四、重载 `==` 运算符
    • 五、重载`前置++` 和 `后置 ++` 运算符
    • 六、重载 `<<` `>>`运算符


一、运算符重载的关键字和注意点

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。函数名字为:关键字operator后面接需要重载的运算符符号。

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

需要注意的点:

(1)不能通过连接其他符号来创建新的操作符:比如operator@

(2)重载操作符必须有一个类类型参数。

(3)用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义。
(4)作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
(5).* :: sizeof ?: . 注意以上5个运算符不能重载。
(6)可以写在类内作为成员函数也可以在全局函数,有一个例外就是赋值运算符只能作为成员函数。

二、重载= 运算符

赋值运算符重载函数是类的默认成员函数,当我们不写的时候编译器会自动生成,又因为是编译器会自动生成的,如果作为全局函数去写的话会与类内的自动生成的赋值运算符重载冲突,所以赋值运算符只能作为成员函数去写。

返回类型 :const 类名 & 返回类的话就可以实现连续赋值了。
函数名:operator=
参数类型:(const & 类名),因为编译器自动会传一个隐含的this ,所以我们传一个参数就够了。

实现:

class Kind
{
public://构造函数Kind(int a = 10,int b = 10){_a = a;_b = b;}//重载 =  //只能作为成员函数  const 防止被修改const Kind & operator=(const Kind& p) {this->_a = p._a;this->_b = p._b;//返回 *this 使其可以连续赋值return *this;	}
private:int _a;int _b;
};int main()
{Kind p1(20, 20);Kind p2;Kind p3;//连续赋值p3 = p2 = p1;cout << "p1: " << p1._a << " " << p1._b << endl;cout << "p2: " << p2._a << " " << p2._b << endl;cout << "p3: " << p3._a << " " << p3._b << endl;return 0;
}

在这里插入图片描述

其实默认的赋值运算符重载函数就是像上写的那样进行赋值,我们对于这样的拷贝叫做浅拷贝,这样做有一个弊端就是如果遇到动态申请的空间的话就有可能发生程序崩溃,这是因为共用一块空间当另一个对象将这块空间释放之后被赋值的那个对象再使用这块空间时就会发生崩溃。

如:

class Kind
{
public://构造函数Kind(int a = 10,int b = 10){_a = a;_b = b;arr = new int;*arr = a; }//重载 =  //只能作为成员函数  const 防止被修改const Kind & operator=(const Kind& p) {this->_a = p._a;this->_b = p._b;this->arr = p.arr;//返回 *this 使其可以连续赋值return *this;	}private:int _a;int _b;int* arr;
};int main()
{Kind p1(20, 20);Kind p2 = p1;return 0;
}

当上述的p1将arr释放了,p2再使用arr就会发生崩溃。
当我们遇到这种情况时我们使用深拷贝

//深拷贝
const Kind& operator=(const Kind& p)
{this->_a = p._a;this->_b = p._b;int* tmp = new int;if (tmp == nullptr)exit(-1);*tmp = *p.arr;this->arr = tmp;//返回 *this 使其可以连续赋值return *this;
}

总结:
当遇到动态申请的空间时需要重写赋值运算符,如果没有用编译器自动生成的即可。

三、重载+ 运算符

1、作为成员函数

返回值: 类型 (类) ,用传值的方式即可,因为返回值是存在栈中当函数销毁时该返回值也会被系统回收。
函数名:operator+
参数:(const & 类名),因为编译器自动会传一个隐含的this ,所以我们传一个参数就够了。

实现:

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}//重载 +  //作为成员函数Kind operator+(const Kind & p){Kind tmp;tmp._a = p._a + this->_a;tmp._b = p._b + this->_b;return tmp;}
private:int _a;int _b;
};int main()
{Kind p1(20, 20);Kind p2(20, 20);Kind  p3 = p1 + p2;cout << "p1: " << p1._a << " " << p1._b << endl;cout << "p2: " << p2._a << " " << p2._b << endl;cout << "p3: " << p3._a << " " << p3._b << endl;return 0;
}

在这里插入图片描述

2、全局函数:
与成员函数不同的是需要多传一个参数,其他的与成员函数一样。

实现:

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}
//作为友元函数,可以访问私有成员。	
friend Kind operator+(const Kind& p1 ,const Kind &p2 );private:int _a;int _b;
};//重载 +  //全局函数Kind operator+(const Kind& p1 ,const Kind &p2  )
{Kind tmp;tmp._a = p1._a + p2._a;tmp._b = p1._b + p2._b;return tmp;
}

3、总结:
可以写全局的函数也可以写成员函数,实现 - * / 运算符重载时的形式与上述的一样。

四、重载 == 运算符

1、作为成员函数

返回值:bool
函数名:operator==
参数:(const &类名),因为编译器自动会传一个隐含的this,所以我们传一个参数就够了。

实现:

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}//重载 ==  //作为成员函数bool operator==(const Kind& p){//成员都相等就相等if (this->_a == p._a && this->_b == p._b)return true;elsereturn false;}
private:int _a;int _b;
};int main()
{Kind p1(20, 20);Kind p2(20, 20);if (p1 == p2){cout << "p1==p2" << endl;}else{cout << "p1!=p2" << endl;}return 0;
}

在这里插入图片描述

2、作为全局函数
与成员函数不同的是需要多传一个参数,其他的与成员函数一样。

实现:

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}
//作为友元函数,可以访问私有成员。	
friend Kind operator==(const Kind& p1 ,const Kind &p2 );private:int _a;int _b;
};//重载 ==  //作为全局函数
bool operator==(const Kind& p1, const Kind& p2)
{if (p1._a == p2._a && p1._b == p2._b)return true;elsereturn false;
}

3、总结
可以写全局的函数也可以写成员函数,实现 != >= <= > < 运算符重载时的形式与上述的一样。

五、重载前置++后置 ++ 运算符

1、前置++
(1)作为成员函数

返回值:返回用引用的方式返回 *this,这样即可进行计算和Kind p2 = ++p1; 和提高效率。
函数名:operator++
参数:无(实际上有一个隐含的this指针)。

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}//重载 前++  //作为成员函数Kind & operator++(){//对成员变量++this->_a++;this->_b++;return *this;}
private:int _a;int _b;
};int main()
{Kind p1(20, 20);cout << p1._a << " " << p1._b << endl;++p1;cout << p1._a << " " << p1._b << endl;return 0;
}

在这里插入图片描述

(2)作为全局函数
多了个参数,其余的一样。

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}
//作为友元函数,可以访问私有成员。	
friend Kind& operator++(Kind& p);private:int _a;int _b;
};
//重载 前置++  //作为全局函数
Kind& operator++(Kind& p)
{//对成员变量++p._a++;p._b++;return p;
}

2、后置++

后置++与前置++的不同是我们在加之前要保存原来的作为返回值,这样才符合后置++运算。
后置++与前置++如何区别捏?
后置++比前置++的参数多一个 int ,这个参数我们不用传值,主要用于区分前置和后置。

(1)作为成员函数

返回值:返回 临时的原来的类
函数名:operator++
参数:(int)(实际上还有一个隐含的this指针)。

实现:

class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}//重载 后置++  //作为成员函数Kind  operator++(int){//对成员变量++Kind p = *this;this->_a++;this->_b++;return p;}
private:int _a;int _b;
};
int main()
{Kind p1(20, 20);cout << p1._a << " " << p1._b << endl;Kind p2 = p1++;cout << p2._a << " " << p2._b << endl;cout << p1._a << " " << p1._b << endl;return 0;
}

在这里插入图片描述

(2)作为全局函数
多了个参数,其余的一样。


class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}//作为友元函数,可以访问私有成员。	
friend Kind  operator++(Kind & tmp,int);
private:int _a;int _b;
};
//重载 后置++  //作为全局函数
Kind  operator++(Kind & tmp,int)
{//对成员变量++Kind p = tmp;tmp._a++;tmp._b++;return p;
}

3、总结
前置和后置的区别在于返回值,他们也可实现全局和成员函数两种,前置 – 和 后置 – 也是类似这样写。

六、重载 << >>运算符

coutostream 类的一个对象,而 << 符在这个类已经进行了一些重载
如:

ostream& operator<<(const int &a)
{//输出代码return *this; 
}

因为在参数列表中会隐含着一个 ostream *this 指针,所以如果我们在其他类将其作为成员函数去重载的话也会传一个隐含的 this 指针,这样的话第一个参数就会与 cout 冲突,所以为了避免冲突我们只能将重载 << 函数作为全局函数。

重载 >>

返回类型 :ostream& 使其能够连续的输出,& 提高效率。
函数名:operator<<
参数:ostream & ost, const Kind& p

//输出ostream & operator<<( ostream& ost, const Kind& p)
{ost << p._a << " " << p._b << endl;return ost;
}

一样的 cinistream类 的对象,>> 也在 istream 类里进行了一些重载。
所以只能在全局里进行重载,原因同上。

重载 >>

返回类型 :istream& 使其能够连续的输出。
函数名:istream<<
参数:istream & ost, const Kind& p

 //输入
istream& operator>>(istream& ist, Kind& p)
{ist >> p._a >> p._b;return ist;
}

测试:

//重载 >> 和 <<
class Kind
{
public://构造函数Kind(int a = 10, int b = 10){_a = a;_b = b;}//作为友元函数,可以访问私有成员。	friend  istream& operator>>(istream& ist, const Kind& tmp);friend	ostream& operator<<(ostream& ost, const Kind& p);
private:int _a;int _b;
};//输出ostream & operator<<( ostream& ost, const Kind& p)
{ost << p._a << " " << p._b << endl;return ost;
}//输入
istream& operator>>(istream& ist, Kind& p)
{ist >> p._a >> p._b;return ist;
}
int main()
{Kind p1;//输入cin >> p1;//输出cout << p1;return 0;
}

在这里插入图片描述

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

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

相关文章

【JavaEE】浅谈线程(一)

线程 前言线程的由来线程是什么线程的属性线程更高效的原因举个例子&#xff08;线程便利性的体现&#xff09; 多线程代码线程并发执行的代码jconsole(观测多线程) 线程的调度问题创建线程的几种方法1&#xff09;通过继承Thread 重写run2&#xff09;使用Runnable接口 重写ru…

MySQL 上亿大表,如何深度优化?

背景 分析 测试 实施 索引优化后 delete大表优化为小批量删除 总结 前段时间刚入职一家公司&#xff0c;就遇上这事&#xff01; 背景 XX实例&#xff08;一主一从&#xff09;xxx告警中每天凌晨在报SLA报警&#xff0c;该报警的意思是存在一定的主从延迟&#xff08;…

【Node】Node的配置文件的使用,dotenv框架的使用

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;Node.js &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续前进的勇…

linux-docker安装nginx

1.拉取镜像&#xff1a; docker pull nginx2.创建挂在路径&#xff1a; mkdir -p /usr/local/nginx/conf mkdir -p /usr/local/nginx/logs mkdir -p /usr/local/nginx/www mkdir -p /usr/local/nginx/conf.d 3.启动镜像:为了拿到位置文件&#xff0c;先启动下 docker run -…

2024 EasyRecovery易恢复 帮你轻松找回回收站删除的视频

随着数字化时代的到来&#xff0c;我们的生活和工作中越来越依赖于电子设备。然而&#xff0c;电子设备中的数据丢失问题也随之而来。数据丢失可能是由各种原因引起的&#xff0c;如硬盘故障、病毒感染、误删除等。面对这种情况&#xff0c;一个高效、可靠的数据恢复工具变得尤…

智慧农场牧场认养系统畜牧养殖积分签到直播监控农资商城养鸡APP小程序支持定制

每日签到&#xff1a;用户每天签到可以获取积分&#xff0c;连续签到7天还有惊喜奖品&#xff0c;这有助于增加用户粘性和活跃度。 我的鸡崽&#xff1a;这一功能以动画形式展示用户的鸡崽状态&#xff0c;新用户可以通过购物满额获得鸡苗&#xff0c;并通过饲喂动作参与鸡的成…

Netty NioEventLoop详解

文章目录 前言类图主要功能NioEventLoop如何实现事件循环NioEventLoop如何处理多路复用Netty如何管理Channel和Selector管理Channel管理Selector注意事项 前言 Netty通过事件循环机制(EventLoop)处理IO事件和异步任务&#xff0c;简单来说&#xff0c;就是通过一个死循环&…

【堡垒机】堡垒机的介绍

目前&#xff0c;常用的堡垒机有收费和开源两类。 收费的有行云管家、纽盾堡垒机&#xff1b; 开源的有jumpserver&#xff1b; 这几种各有各的优缺点&#xff0c;如何选择&#xff0c;大家可以根据实际场景来判断 什么是堡垒机 堡垒机&#xff0c;即在一个特定的网络环境下&…

李沐23_LeNet——自学笔记

手写的数字识别 知名度最高的数据集&#xff1a;MNIST 1.训练数据&#xff1a;50000 2.测试数据&#xff1a;50000 3.图像大小&#xff1a;28✖28 4.10类 总结 1.LeNet是早期成功的神经网络 2.先使用卷积层来学习图片空间信息 3.使用全连接层来转换到类别空间 代码实现…

【oracle数据库安装篇一】Linux5.6基于LVM安装oracle10gR2单机

说明 本篇文章主要介绍了Linux5.6基于LVM安装oracle10gR2单机的配置过程&#xff0c;比较详细&#xff0c;基本上每一个配置部分的步骤都提供了完整的脚本&#xff0c;安装部分都提供了简单的说明和截图&#xff0c;帮助你100%安装成功oracle数据库。 安装过程有不明白的地方…

二维相位解包理论算法和软件【全文翻译- DCT相位解包裹(5.3.2)】

5.3.2 基于 DCT 的方法 在本节中,我们将详细介绍如何通过 DCT 算法解决非加权最小二乘相位解缠问题,而不是通过FFT.我们将使用公式 5.53 所定义的二维余弦变换。我们开发的算法等同于 FFT 方法 2(第 5.3.1 节)。与 FFT 方法 I 等价的 DCT 算法也可以推导出来,但我们将其作…

PlayerSettings.WebGL.emscriptenArgs设置无效的问题

1&#xff09;PlayerSettings.WebGL.emscriptenArgs设置无效的问题 2&#xff09;多个小资源包合并为大资源包的疑问 3&#xff09;AssetBundle在移动设备上丢失 4&#xff09;Unity云渲染插件RenderStreaming&#xff0c;如何实现多用户分别有独立的操作 这是第381篇UWA技术知…

Meta 的 Llama 模型系列即将迎来第三次大更新

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

linux启动流程(s3c2400)

概述 大致流程&#xff1a;内核&#xff08;kernel&#xff09;都是由bootloader程序引导启动的&#xff0c;所以我们应该先烧进去bootloader程序。然后可以通过保存的内核代码或者通过远程连接&#xff08;nfs/tftp&#xff09;的主机下载再运行&#xff0c;再挂载根文件系统。…

ppt从零基础到高手【办公】

第一章&#xff1a;文字排版篇01演示文稿内容基密02文字操作规范03文字排版处理04复习&作业解析第二章&#xff1a;图形图片图表篇05图形化表达06图片艺术化07轻松玩转图表08高效工具&母版统一管理09复习&作业解析10轻松一刻-文字图形小技巧速学第三章&#xff1a;…

SWM341系列应用(RTC、FreeRTOS\RTTHREAD应用和Chip ID)

SWM341系列RTC应用 22.1、RTC的时钟基准 --liuzc 2023-8-17 现象:客户休眠发现RTC走的不准&#xff0c;睡眠2小时才走了5分钟。 分析与解决&#xff1a;经过排查RTC的时钟源是XTAL_32K&#xff0c;由于睡眠时时设置XTAL->CR0&#xff1b;&#xff0c;会把XTAL_32K给关…

C语言:指针详解(1)

目录 一、内存和地址 1.内存 2.究竟该如何理解编址 二、指针变量和地址 1.取地址操作符(&) 2.解引用操作符(*) 3.指针变量的大小 三、指针变量类型的意义 1.指针的解引用 2.指针-整数 3.void*指针 四、const修饰指针 1.const修饰变量 2.const修饰指针变量 五…

公开课学习——仿抖音直播平台

文章目录 直播抖音的直播原理Java继承直播客户端工具&#xff1a; ffmpeg客户端和网页集成CDN网络——性能提升关键——边缘计算 实时聊天——IM系统怎么实现&#xff1f;——websocketIM系统消息如何转发&#xff1f;直播场景IM系统是什么样子&#xff1f; 直播 抖音的直播原…

安全操作代码优化思路

理论依据 数据增强和样本选择 在训练阶段&#xff0c;您可以考虑添加数据增强来提升模型的鲁棒性和泛化能力。针对人脸检测任务&#xff0c;可以尝试以下改进&#xff1a; 对输入图像进行随机裁剪、缩放、旋转、翻转等数据增强操作&#xff0c;以增加数据的多样性。 使用难样…

操作系统—修改xv6内核调度算法

文章目录 修改xv6内核调度算法1.实验环境2.基于优先级的调度算法(1).基本实现思路(2).实现流程(3).一些问题 3.乐透调度算法(1).思路(2).实现流程(3).一些问题 总结参考资料 修改xv6内核调度算法 1.实验环境 这一次的实验因为是在xv6内核中实现一些调度算法&#xff0c;因此我…