C++ 类和对象篇(七) 运算符重载

news2024/9/23 7:21:59

目录

一、运算符重载

1. 运算符重载是什么?

2. 为什么要运算符重载?

3. 怎么进行运算符重载?

a. 运算符重载函数的格式

b. 参数的个数和要重载的运算符操作数相同

c. 运算符重载函数必须有一个类类型参数

 4. 注意事项

二、 赋值运算符重载

1. 默认赋值运算符重载函数

2. 赋值运算符只能在类中重载

3. 在类中显示重载赋值运算符

4. 两边必须是已经存在的对象才会调用赋值运算符重载函数


一、运算符重载

1. 运算符重载是什么?

        运算符重载是一种在编程中扩展或改变已有运算符功能的技术。简单来说,运算符重载就是对已有的运算符重新进行定义,让运算符能够处理特定类型的对象。

2. 为什么要运算符重载?

如果想要让两个对象比较大小该怎么办?有没有办法直接使用运算符>, <来比较两个对象的大小?

class A
{
public:
	A(int a)
	{
		num = a;
	}
	int max(A b)
	{
		return num > b.num;
	}
	int operator> (A b)
	{
		return num > b.num;
	}
private:
	int num;
};
int main()
{
	A a(10);
	A b(20);
    //如果不使用运算符重载,只能编写函数来比较两个对象的大小
	cout << a.max(b) << endl;
    //使用运算符重载
    cout << (a > b) << endl;
	return 0;
}

运算符重载的目的是为了让自定义类型能够使用运算符。
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,其目的就是让自定义类型可以像内置类型一样可以直接使用运算符进行操作。

3. 怎么进行运算符重载?

a. 运算符重载函数的格式

        运算符重载函数的函数名是operator加要重载的运算符,有返回值和参数,参数的个数和要重载的运算符操作数相同,且必须有一个类类型参数

格式:返回值类型 operator操作符 (参数列表)
运算符重载函数函数可以写在类内,也可以在类外:
class A
{
public:
	A(int a)
	{
		num = a;
	}
    // 类内的运算符重载函数
    // 参数的个数和要重载的运算符操作数相同(类的成员函数参数隐藏了一个this指针。)
	int operator> (A b)
	{
		return num > b.num;
	}
private:
	int num;
};
class B
{
public:
	B(int a)
	{
		num = a;
	}
private:
	int num;
};
// 类外的运算符重载函数
// 参数的个数和要重载的运算符操作数相同
int operator> (A a, B b)
{
	return 1;
}
int operator> (A a, int b)
{
	return 0;
}

b. 参数的个数和要重载的运算符操作数相同

        要注意的是类的成员函数参数隐藏了一个this指针,所以在类内重载运算符时,参数个数要减一。

在类内重载>时参数太少:

在类内重载>时参数太多:


c. 运算符重载函数必须有一个类类型参数

类外的运算符重载函数必须显示的传入一个类类型参数。

类内的运算符重载函数,是类的成员函数,所以编译器会传入一个this指针,这相当于已经有了一个类类型参数,所以可以不写类类型参数。

 4. 注意事项

  • operator后面不能连接非运算符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 运算符重载函数作为类成员函数时,它的第一个参数为隐藏的this指针,所以对于只需要两个参数的运算符,我们在类中重载时传一个参数即可。

  • 逗号运算符   ::(域作用限定符)   sizeof运算符   ?:(三目运算符)   成员函数运算符(.和->) 以上5个运算符不能重载。这个经常在笔试选择题中出现。
  • 无法在类外重载=

二、 赋值运算符重载

1. 默认赋值运算符重载函数

        赋值运算符重载函数的特殊在于:只能在类中定义,用户在类中没有显式实现时,编译器会生成一个默认赋值运算符重载函数,以值的方式逐字节拷贝。注意:默认赋值运算符重载函数里内置类型成员变量是直接赋值的,而自定义类型成员变量会调用对应类的赋值运算符重载函数完成赋值:


默认赋值运算符重载函数会调用自定义类型成员变量对应类的赋值运算符重载函数完成赋值:

// operator=(=的重载)是类的默认成员函数。即使你不写,编译器也会自动生成的,实现一个对象对另一个对象的浅拷贝。
// 自定义类型成员变量会调用对应类的赋值运算符重载函数完成赋值。
class A
{
public:
	A& operator= (const A& a)
	{
		cout << "A的赋值运算符重载函数被调用" << endl;
		num = a.num;
		return *this;
	}
private:
	int num;
};

class B{
private:
	A a;
};

int main()
{
	B b, c;
	c = b;
	return 0;
}

2. 赋值运算符只能在类中重载

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

3. 在类中显示重载赋值运算符

一个标准的赋值运算符重载函数应该做到以下几点:

  • 参数类型:const T&,传递引用可以提高传参效率
  • 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值。
  • 有条件判断,能检测是否自己给自己赋值
  • 返回 *this :为了支持连续赋值。
一个标准的 =重载:
class A
{
public:
    // 参数类型:const T&,传递引用可以提高传参效率。
    // 返回值使用传引用返回,这样可以减少使用拷贝构造函数。
	A& operator= (const A& a)
	{
        // 有条件判断,能检测是否自己给自己赋值.
        if(this != &a)
        {
		    num = a.num;   
        }
        // this是对象的指针,加*解引用返回对象本身,这样能支持连续赋值。
		return *this;
	}
private:
	int num;
};

4. 两边必须是已经存在的对象才会调用赋值运算符重载函数

=两边是两个已经存在的对象才是赋值,才会调用赋值运算符。

在以下在例子中的虽然是用=,但仍是调用拷贝构造:
class A
{
public:
	A() {}
	A(const A& a)
	{
		cout << "A的拷贝构造函数被调用" << endl;
	}
	A& operator= (const A& a)
	{
		cout << "A的赋值运算符重载函数被调用" << endl;
		num = a.num;
		return *this;
	}
private:
	int num;
};

int main()
{
	A b;
	A c = b;
	return 0;
}

对象b存在,对象c不存在:

对象b,c都存在才是赋值才会调用赋值运算符重载函数:


------------------------END-------------------------

才疏学浅,谬误难免,欢迎各位批评指正。

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

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

相关文章

提升企业形象与效率,申请办理400电话客服中心

引言&#xff1a; 随着企业竞争的日益激烈&#xff0c;提供优质的客户服务成为企业赢得市场份额的关键。而400电话客服中心的建立&#xff0c;不仅可以提升企业形象&#xff0c;还能提高客户满意度和工作效率。本文将介绍400电话客服中心的申请办理过程&#xff0c;以及其对企业…

Starrc读lef遇到的常见错误

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 ERROR: the definition cell "BUFXX" instantiated as xx in DEF file xx is not found.(SX-2144) ERROR: Instance xx has no definition. (SX-2505) 这个问题就是典型的lef数据不全,…

lua学习笔记

单行注释&#xff1a; 多行注释&#xff1a; 命名&#xff1a; Lua不支持下划线大写字母&#xff0c;比如&#xff1a;_ABC 但支持&#xff1a;_abc 关键字&#xff1a; 全局变量&#xff1a; 直接变量名 内容就是全局 局部变量&#xff1a; 加上local即可 nil&#xff1…

【多线程案例】阻塞队列,实现生产者消费者模型

阻塞队列&#xff08;BlockingQueue&#xff09; 阻塞队列是多线程代码中比较常用的一种数据结构。是一种特殊的队列&#xff0c;带有阻塞特性。 为何说是一种特殊的队列&#xff1f; 1.线程安全 2.带有阻塞特性 如果队列为空&#xff0c;继续出队列&#xff0c;就会发生阻塞…

零基础Linux_13(基础IO_文件)文件系统接口+文件描述符fd+dup2函数

目录 1. C语言的文件操作 1.1 C语言文件的写入 1.2 当前路径 1.3 文件操作模式 1.4 文件的读取和cat 2. 文件系统接口 2.1 系统调用与封装 2.2 open打开文件 2.2.1 flags标记位 2.2.2 open用法演示 2.3 close关闭文件和write写入文件和rede读取文件 2.3.1 O_TRUNC…

基于JSP的动漫论坛

摘 要 作为文化产业的一部分&#xff0c;动漫影响了我国一代又一代青少年&#xff0c;据钱江晚报调查显示&#xff0c;有超过七成的95后愿意从事与动漫相关的行业&#xff0c;可见其对青少年影响力之大。 动漫论坛作为最先开始热爱动漫人士进行交流的方式之一&#xff0c;是爱…

Reactor网络模式

文章目录 1. 关于Reactor模式的了解2. 基于Reactor模式实现epoll ET服务器2.1 EventItem类的实现2.2 Reactor类的实现Dispatcher函数AddEvent函数DelEvent函数EnableReadWrite函数 2.3 四个回调函数的实现acceptor回调函数recver回调函数sender回调函数errorer回调函数 3. epol…

TensorFlow入门(十五、数据读取机制(2))

使用Dataset创建和读取数据集,作为TensorFlow模型创建输入管道的新方式,使用性能比使用feed_dict或队列式管道的性能高很多,使用也更加简洁容易。也是google强烈推荐的数据读取方式,对于TensorFlow而言,十分重要。 Dataset是什么? Dataset的定义 : 它是一个含有相同类型元素且…

C++局部变量 成员变量 全局变量(及文件内外全局变量)

在C中&#xff0c;类的局部变量、成员变量、全局变量、静态全局变量&#xff1a; 局部变量&#xff1a;局部变量是在函数内部定义的变量&#xff0c;它只能在该函数的范围内被访问和修改。当函数执行结束后&#xff0c;局部变量的内存空间会被释放。局部变量主体是函数。局部变…

如何成为一名云计算构架师,看这里!

都说&#xff0c;每个程序员心中都有一个成为架构师的梦想&#xff01; 因为不管是对于自身专业技能的认可&#xff0c;还是立足于现实的薪资&#xff0c;都是令人向往的&#xff01; 1.云计算架构师介绍 云计算架构师负责管理企业中的云计算架构&#xff0c;尤其是在云技术…

P1867 【Mc生存】经验值

#include <stdio.h>int main(void) {int n; //n项操作double HP 10; //总生命值&#xff0c;初始化为10&#xff0c;上限是10int LV 0; //等级&#xff0c;初始化为1int EXP 0; //总经验值&#xff0c;初始化为0double de_HP; //减少的生命值int in_EXP; //增加…

react学习(三——实战项目)

创建 npm init vite小知识 "scripts": {"dev": "vite --host --port 3002 --open", //--host会在终端显示IP&#xff0c;--port 3002把显示端口改为3002&#xff0c;--open会在启动后打开链接"build": "tsc && vite bui…

如何自学(黑客)网络安全技术————(详细分析学习思路)

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0…

IIC总线

IIC总线原理 时序图作业 MPU6050 MPU6050是一个运动处理传感器&#xff0c;其内部集成了3轴加速度传感器 和3轴陀螺仪&#xff08;角速度传感器&#xff09;,以及一个可扩展数字运动处理器

php伪协议 [ACTF2020 新生赛]Include1

打开题目 点击后 期间bp抓包也一无所获 那我们回到题目上来 我们可知这是文件包含漏洞&#xff0c;但是我们直接读取的是flag.php文件&#xff0c;而非flag.php文件源码&#xff0c;那我们想要获取文件源码&#xff0c;这里就涉及到php伪协议 php://filter可以获取指定文件源码…

typename、typedef、using对比

在c的标准库中&#xff0c;因为类继承关系比较复杂和模板使用比较多的原因&#xff0c;源代码中充斥着typename、typedef和using这三个关键字 一、typename关键字 1.1、typename的第一个作用是用作模板里面&#xff0c;来声明某种类型 template<typename _Tp, typename _…

根据二叉树创建字符串--力扣

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

stm32 hal库 st7789 1.54寸lcd

文章目录 前言一、软件spi1.cubemx配置2.源码文件 二、硬件spi1.cubemx配置2.源码文件3.小小修改 总结 前言 1.54寸lcd 240*240 一、软件spi 1.cubemx配置 一定要注意把这几个东西上拉。 使用c8 2.源码文件 我使用的是中景园的源码&#xff0c;他本来是是标准库的稍微修改…

死灰复燃!QakBot 恶意软件仍在运行中

2023 年 8 月&#xff0c;美国联邦调查局宣布&#xff0c;在名为“猎鸭行动”的国际执法活动中&#xff0c;成功拆除 Qakbot 僵尸网络&#xff08;Qakbot 也称 QBot、QuackBot 和 Pinkslipbot&#xff0c;自 2008 年以来一直非常活跃&#xff09;。然而 Security A ffairs 网站…

好用的便签软件如何实现定时提醒?支持设定定时提醒的便签

不论你是职场白领&#xff1f;还是销售精英&#xff1f;亦或者是家庭主妇&#xff0c;每天都会面临着大量的事务需要处理&#xff0c;怎么才能高效规划管理自己每日事务&#xff0c;以及进行时间管理成为一项比较重大的挑战&#xff0c;便签类软件可以辅助大家按时完成各项任务…