C++ 运算符重载 (备查)

基础

运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

运算符重载也可以发生函数重载

语法:

void operator@();	//@代表了被重载的运算符。

函数的参数个数取决于两个因素。
	1)运算符是一元(一个参数)的还是二元(两个参数)2)运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)
	还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)

成员函数重载 + 全局函数重载 原理

在这里插入图片描述

运算符重载(operator overloading)只是一种”语法上的方便”,也就是它只是另一种函数调用的方式。

是否可重载

在这里插入图片描述

几乎C中所有的运算符都可以重载,但运算符重载的使用时相当受限制的。

不能改变运算符优先级,不能改变运算符的参数个数。

加号(+)运算符重载

//利用成员函数实现加号运算符重载
Person operator+(Person &p)
{
	Person temp;
	temp.m_A = this->m_A + p.m_A;
	temp.m_B = this->m_B + p.m_B;
	return temp;
}

private:
	int m_A;
	int m_B;
//利用全局函数实现加号运算符重载
Person operator+(Person &p1, Person &p2)
{
	Person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}

重载左移操作符(<<),使得 cout 可以输出自定义对象

为什么不用 成员函数重载 实现

在这里插入图片描述

使用 全局函数 重载 << 运算符(无法链式编程)

在这里插入图片描述

cout 是 ostream 类的对象,全局只有一个,所以使用 & 。

要实现 cout 链式输出需返回 cout 引用

在这里插入图片描述

如果要访问类中私有属性,配合友元实现
//重载 << 运算符案列
class Person{
	friend ostream& operator<<(ostream& os, Person& person);//友元
public:
	Person(int id,int age){
		mID = id;
		mAge = age;
	}
private:
	int mID;
	int mAge;
};

//重载 <<  运算符
ostream& operator<<(ostream& os, Person& person){
	os << "ID:" << person.mID << " Age:" << person.mAge;
	return os;
}

int main(){

	Person person(1001, 30);
	//cout << person; //cout.operator+(person)
	cout << person << " | " << endl;

	return EXIT_SUCCESS;
}

自增自减(++/–)运算符重载

class Complex{

public:
	Complex(){
		mA = 0;
		mB = 0;
	}
	//重载前置++
	Complex& operator++(){
		mA++;
		mB++;
		return *this;	//返回的的是引用,可以实现链式编程:(++(++b))
	}
	//重载后置++
	Complex operator++(int){	
		Complex temp;
		temp.mA = this->mA;
		temp.mB = this->mB;
		mA++;
		mB++;
		return temp;	//temp是局部对象,不能返回引用,所以不能实现链式编程。
	}
	//前置--
	Complex& operator--(){
		mA--;
		mB--;
		return *this;
	}
	//后置--
	Complex operator--(int){
		Complex temp;
		temp.mA = mA;
		temp.mB = mB;
		mA--;
		mB--;
		return temp;
	}

private:
	int mA;
	int mB;
};

如何区分重载的前置++还是后置++,通过占位参数来区分,有 int 的为后置++,- - 同理。

要优先使用前缀形式,由于前缀形式创建了一个临时对象,效率经常会略高一些。

指针运算符( *、-> )重载

利用智能指针,管理 new 出来的 Person 的释放操作。

//被维护的类
class Person{
public:
	Person(int param){
		this->mParam = param;
	}
	void PrintPerson(){
		cout << "Param:" << mParam << endl;
	}
private:
	int mParam;
};

//智能指针
class SmartPointer{
public:
	SmartPointer(Person* person){
		this->pPerson = person;
	}
	
	//重载指针的 -> 操作符
	Person* operator->(){
		return pPerson;
	}
	//重载指针的 * 操作符
	Person& operator*(){
		return *pPerson;
	}
	
	~SmartPointer(){
		if (pPerson != NULL){
			delete pPerson;	//在析构中释放 被维护对象空间
			this.pPerson = NULL;
		}
	}
public:
	Person* pPerson;	//维护一个被管理类的指针
};

void test01(){
	SmartPointer pointer(new Person(18));	//通过构造,实例化被被维护的对象
	
	//本质:pointer->->PrintPerson(); 编译器简化为:pointer->PrintPerson();
	pointer->PrintPerson();	
	(*pointer).PrintPerson();
}

智能指针类 执行在栈上,执行完后自动释放,同时也释放了被维护对象的空间。

自动释放体现出:智能
指针运算符( * ,-> )重载体现出: 指针

赋值(=)运算符重载

编译器 默认给一个类提供四个函数:默认构造,拷贝构造(浅拷贝),析构函数 ,operator= (浅拷贝)。

在这里插入图片描述

//赋值(=)运算符重载-------详细案列
class Person{
	friend ostream& operator<<(ostream& os,const Person& person){
		os << "ID:" << person.mID << " Age:" << person.mAge << endl;
		return os;
	}
public:
	Person(int id,int age){
		this->mID = id;
		this->mAge = age;
	}
	//重载赋值运算符
	Person& operator=(const Person& person){
		this->mID = person.mID;
		this->mAge = person.mAge;
		return *this;
	}
private:
	int mID;
	int mAge;
};

//1. =号混淆的地方
void test01(){
	Person person1(10, 20);
	Person person2 = person1; //调用拷贝构造
	//如果一个对象还没有被创建,则必须初始化,也就是调用构造函数
	//上述例子由于person2还没有初始化,所以会调用构造函数
	//由于person2是从已有的person1来创建的,所以只有一个选择
	//就是调用拷贝构造函数
	person2 = person1; //调用operator=函数
	//由于person2已经创建,不需要再调用构造函数,这时候调用的是重载的赋值运算符
}
//2. 赋值重载案例
void test02(){
	Person person1(20, 20);
	Person person2(30, 30);
	cout << "person1:" << person1;
	cout << "person2:" << person2;
	person2 = person1;
	cout << "person2:" << person2;
}
//常见错误,当准备给两个相同对象赋值时,应该首先检查一下这个对象是否对自身赋值了
//对于本例来讲,无论如何执行这些赋值运算都是无害的,但如果对类的实现进行修改,那么将会出现差异;
//3. 类中指针
class Person2{
	friend ostream& operator<<(ostream& os, const Person2& person){
		os << "Name:" << person.pName << " ID:" << person.mID << " Age:" << person.mAge << endl;
		return os;
	}
public:
	Person2(char* name,int id, int age){
		this->pName = new char[strlen(name) + 1];
		strcpy(this->pName, name);
		this->mID = id;
		this->mAge = age;
	}
#if 1
	//重载赋值运算符
	Person2& operator=(const Person2& person){

		//注意:由于当前对象已经创建完毕,那么就有可能pName指向堆内存
		//这个时候如果直接赋值,会导致内存没有及时释放
		if (this->pName != NULL){
			delete[] this->pName;
		}

		this->pName = new char[strlen(person.pName) + 1];
		strcpy(this->pName,person.pName);
		this->mID = person.mID;
		this->mAge = person.mAge;
		return *this;
	}
#endif
	//析构函数
	~Person2(){
		if (this->pName != NULL){
			delete[] this->pName;
		}
	}
private:
	char* pName;
	int mID;
	int mAge;
};

void test03(){
	Person2 person1("John",20, 20);
	Person2 person2("Edward",30, 30);
	cout << "person1:" << person1;
	cout << "person2:" << person2;
	person2 = person1;
	cout << "person2:" << person2;
}

等于和不等于(==、!=)运算符重载

class Complex{
public:
	Complex(char* name,int id,int age){
		this->pName = new char[strlen(name) + 1];
		strcpy(this->pName, name);
		this->mID = id;
		this->mAge = age;
	}
	//重载==号操作符
	bool operator==(const Complex& complex){
		if (strcmp(this->pName,complex.pName) == 0 && 
		    this->mID == complex.mID && 
			this->mAge == complex.mAge){
			return true;
		}
		return false;
	}
	//重载!=操作符
	bool operator!=(const Complex& complex){
		if (strcmp(this->pName, complex.pName) != 0 || 
		    this->mID != complex.mID || 
			this->mAge != complex.mAge){
			return true;
		}
		return false;
	}
	~Complex(){
		if (this->pName != NULL){
			delete[] this->pName;
		}
	}
private:
	char* pName;
	int mID;
	int mAge;
};
void test(){
	Complex complex1("aaa", 10, 20);
	Complex complex2("bbb", 10, 20);
	if (complex1 == complex2){ cout << "相等!" << endl; }
	if (complex1 != complex2){ cout << "不相等!" << endl; }
}

函数调用符号()重载——(仿函数)

class Complex{
public:
	int Add(int x,int y){
		return x + y;
	}
	int operator()(int x,int y){
		return x + y;
	}
};
void test01(){
	Complex complex;
	cout << complex.Add(10,20) << endl;
	//对象当做函数来调用
	cout << complex(10, 20) << endl;
	//使用匿名对象 用完立即释放
	cout << complex()(10, 20) << endl;
}

不要重载&&、||

不能重载 operator&& 和 operator|| 的原因是,无法在这两种情况下实现内置操作符的完整语义。(即:不能实现短路特性

符号重载建议

在这里插入图片描述

=, [], () 和 -> 操作符只能通过成员函数进行重载

<< 和 >>只能通过全局函数配合友元函数进行重载

不要重载 && 和 || 操作符,因为无法实现短路规则

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

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

相关文章

zerotier实现内网穿透(访问内网服务器)

moo 内网穿透工具 实用工具&#xff1a;zerotier 目录 内网穿透工具 Windows下zerotier安装 ubuntu系统下的zerotier安装 使用moon加速 Windows下zerotier安装 有了网络之后&#xff0c;会给你一个网络id&#xff0c;这个网络id是非常重要的&#xff0c;其它设备要加入…

【C++】刷题强训(day14)--乒乓球匡、组队竞赛、删除相邻数字的最大分数

目录 1、乒乓球匡 1.1题目 1.2 思路 1.3 代码实现 2、组队竞赛 2.1 题目 2.2 思路 2.3 代码实现 3、删除相邻数字的最大分数 3.2 思路 3.3 代码实现 刷题汇总&#xff1a;传送门&#xff01; 1、乒乓球匡 1.1题目 1.2 思路 这道题注意一下示例&#xff0c;<br…

Windows安装elasticsearch、Kibana以及IK分词器

一、下载 1.下载elasticsearch 访问官网Download Elasticsearch | Elastic&#xff0c;下载elasticsearch 2.下载 Kibana 访问Download Kibana Free | Get Started Now | Elastic &#xff0c;下载 Kibana 3. IK分词器下载 访问Gitee 极速下载/elasticsearch-analysis-ik选…

STM32输入捕获详解

目录 一、引言 二、输入捕获原理 三、寄存器介绍 四、配置步骤 1.开启时钟 2.GPIO 初始化 3.初始化定时器 4.配置输入捕获模式 5.使能捕获和更新中断 6.设置中断分组并编写中断服务函数 7.使能定时器 五、程序示例 六、总结 一、引言 在嵌入式系统开发中&#xff0…

聚类及Python下实现 K-means 算法

聚类 聚类是无监督学习中的一种重要方法&#xff0c;旨在将数据集中相似的数据对象划分到同一个簇中&#xff0c;使得不同簇之间的数据对象差异尽可能大。在大数据环境下&#xff0c;聚类可以帮助挖掘数据中的隐藏结构和模式&#xff0c;应用场景十分广泛&#xff0c;比如在客…

开源分布式系统追踪-01-Zipkin-01-入门介绍

分布式跟踪系列 CAT cat monitor 分布式监控 CAT-是什么&#xff1f; cat monitor-02-分布式监控 CAT埋点 cat monitor-03-深度剖析开源分布式监控CAT cat monitor-04-cat 服务端部署实战 cat monitor-05-cat 客户端集成实战 cat monitor-06-cat 消息存储 skywalking …

解决Jmeter HTTP Cookie管理器cookie不生效

解决Jmeter HTTP Cookie管理器cookie不生效问题 解决Jmeter HTTP Cookie管理器cookie不生效问题1、设置Jmeter HTTP Cookie管理器cookie后&#xff0c;发起的请求显示[no cookies]jmeter问题复现&#xff1a;这里同样使用postman进行重试&#xff0c;发现是可以正常获取数据的&…

【6】数据分析检测(DataFrame 1)

学习目标3 昨天&#xff0c;我们学习了Series。 而Pandas的另一种数据类型&#xff1a;DataFrame&#xff0c;在许多特性上和Series有相似之处。 今天&#xff0c;我们将学习DataFrame的相关知识&#xff1a; 1. DataFrame的概念 2. 构造一个DataFrame 3. DataFrame的常用…

LeetCode 热题 100_环形链表 II(26_142_中等_C++)(单链表;哈希表;快慢指针)

LeetCode 热题 100_环形链表 II&#xff08;26_142&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;代码实现&#xff08;思路一&#xff08;哈希表&#xff09;&#xff09;&#xff1a;代码实现&#xff08;思路二&#xff0…

如何通过看板进行跨境电商的圣诞商品数据分析与优化选品流程?

引言 随着圣诞季的临近&#xff0c;跨境电商迎来了重要的销售时机。选品工作对于跨境电商的成功至关重要&#xff0c;直接关系到销售业绩和利润。本文结合相关网页信息&#xff0c;深入探讨跨境电商在圣诞期间如何利用信息整合工具展开选品工作&#xff0c;并优化选品流程。同…

PHP开发设计模式:单例模式

PHP开发设计模式&#xff1a;单例模式 特点&#xff1a; 三私一公&#xff1a;私有的静态变量&#xff08;存放实例&#xff09;&#xff0c;私有的构造方法&#xff08;防止创建实例&#xff09;&#xff0c;私有的克隆方法 (防止克隆对象)&#xff0c;公有的静态方法&#…

使用HTML获取商品详情:技术实现与最佳实践

1. 引言 在电子商务领域&#xff0c;获取商品详情是提升用户体验和增强网站功能性的关键。本文将探讨如何使用HTML结合其他技术手段获取商品详情&#xff0c;并展示如何将这些信息有效地呈现给用户。 2. 理解商品详情页面的结构 在开始编码之前&#xff0c;我们需要了解商品…

MR30分布式IO在新能源领域加氢站的应用

导读 氢能被誉为21世纪最具发展潜力的清洁能源&#xff0c;氢能科技创新和产业发展持续得到各国青睐。氢能低碳环保&#xff0c;燃烧的产物只有水&#xff0c;是用能终端实现绿色低碳转型的重要载体。氢能产业链分别为上游制氢、中游储运以及下游用氢。上游制氢工艺目前大部分…

WEB安全基础知识

WAF全称为Web Application Firewall&#xff08;网页应用防火墙&#xff09;是一种专门设计用来保护web应用免受各种网络攻击的安全防护措施。它位于客户端与服务器之间&#xff0c;监控和过滤HTTP流量&#xff0c;从而拦截恶意请求、识别并防御常见的web攻击。 WAF的主要功能…

【数据结构】B树家族解析:B树、B+树与B*树的理论与B树插入实现(C++)

文章目录 一、常见的搜索结构二、B树2.1 B树概念2.2 开销 三、代码实现3.1 B树节点的设计3.2 B树设计3.3 插入操作实现1. 查找插入位置&#xff08;Find 函数&#xff09;2. 插入关键字到节点&#xff08;InsertKey 函数&#xff09;3. 处理节点分裂&#xff08;Insert 函数&am…

protobuf c++开发快速上手指南

1、环境准备 在c环境使用 protobuf&#xff0c;需要安装protobuf runtime以及protobuf的编译器&#xff1a;protoc&#xff0c;其作用如下表格&#xff1a; 需要安装的环境作用protoc将proto文件编译成c源码protobuf runtime编译c源码需要链接到protobuf库 注意&#xff1a;…

【实践·专业课】内存管理-存储管理-文件系统

1. 基于Linux的简单区块链实现 1.1. 环境准备 确保使用的 Linux 系统&#xff08;如 Ubuntu、CentOS 等&#xff09;已安装 Python 3。 在终端输入python3命令&#xff0c;若出现 Python 解释器的版本信息等提示&#xff0c;则表示已安装&#xff1b; 若提示未找到命令&…

科技潮头浪接天,一桥飞架两界连。EthernetIP转Profinet互译连

本案例介绍的是西门子1200PLC通过稳联技术PROFINET转EtherNetIP网关&#xff08;WL-ABC2006&#xff09;连接HCS-6100系统配置案例。 打开稳联技术Ethernetip转profient网关(WL-ABC2006)配置软件&#xff0c;因为网关作为EtherNetIP从站&#xff0c;所以选择PN2EIP。设置网关Pr…

【网络篇】TCP知识

TCP首部格式&#xff1f; 为什么需要 TCP 协议&#xff1f; TCP 工作在哪一层&#xff1f; IP 层是不可靠的&#xff0c;它不保证网络包的交付、不保证网络包的按序交付也不保证网络包中的数据的完整性。如果需要保障网络数据包的可靠性&#xff0c;那么就需要由上层&#xff0…

PDFMathTranslate,PDF多语言翻译,批量处理,学术论文,双语对照(WIN/MAC)

分享一个非常实用的PDF文档翻译项目——PDFMathTranslate。作为一个经常逛GitHub的开发者&#xff0c;我总喜欢翻看各种项目附带的论文&#xff0c;虽然大多时候是瞎研究&#xff0c;但却乐在其中。该项目能够完美保留公式、图表、目录和注释&#xff0c;对于需要阅读外文文献的…