【C++学习】类和对象--运算符重载

news2024/10/5 14:42:49

运算符重载概念:对已有运算符重新定义,赋予其另一种功能,以适应不同的数据类型。

作用:实现两个自定义数据类型相加的运算。

目录

加号运算符重载

1.成员函数重载+

 2.全局函数重载+

        左移运算符重载<<

        递增运算符重载

        赋值运算符重载

        关系运算符重载

        函数调用运算符重载


加号运算符重载

1.成员函数重载+

#include<iostream>
#include<string>
using namespace std;
//加号运算符重载
class person
{
public:
	//1.成员函数重载+
	person operator + (person &p)//传入一个person类
	{
		person temp;
		temp.m_a = this->m_a + p.m_a;
		temp.m_b = this->m_b + p.m_b;
		return temp;
	}
	int m_a;
	int m_b;
};
void test01()
{
	person p1;
	p1.m_a = 10;
	p1.m_b = 10;
	person p2;
	p2.m_a = 10;
	p2.m_b = 10;
	person p3 = p1 + p2;
	cout << p3.m_a << " " << p3.m_b;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

 2.全局函数重载+

#include<iostream>
#include<string>
using namespace std;
//加号运算符重载
class person
{
public:

	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;
}
void test01()
{
	person p1;
	p1.m_a = 10;
	p1.m_b = 10;
	person p2;
	p2.m_a = 10;
	p2.m_b = 10;
	person p3 = p1 + p2;
	cout << p3.m_a << " " << p3.m_b;
}

//2.全局函数重载+

int main()
{
	test01();

	system("pause");
	return 0;
}
	//成员函数重载本质调用
	person p3 = p1.operator +(p2);
	//全局函数重载本质调用
	person p3 = operator+(p1, p2);
    //简化版
    person p3=p1+p2;

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

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;
}
person operator +(person& p1, int num)
{
	person temp;
	temp.m_a = p1.m_a + num;
	temp.m_b = p1.m_b + num;
	return temp;
}

总结1:对于内置的数据的表达式运算符是不可能改变的

                                        //最好只改变自定义类型表达式运算符

总结2:不要滥用运算符重载

左移运算符重载<<

作用:可以输出自定义的数据类型

#include<iostream>
#include<string>
using namespace std;
//左移运算符重载
class person
{
public:
	
	int m_a;
	int m_b;
};
//只能利用全局函数重载左移运算符
ostream& operator<<(ostream& nixx, person& p)
{//本质  operator<<(cout,p) ,简化   cout<<p
	nixx << p.m_a << " " << p.m_b ;
	return nixx;
}
void test01()
{
	person p;
	p.m_a = 10;
	p.m_b = 10;
	cout << p<<"    i want to play LOL"<<endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

递增运算符重载

作用:通过重载递增运算符,实现自己的整型数据

	//重载++运算符,++a
	myinteger& operator++()//如果返回 值,myint就只能进行一次递增
	{
		m_num++;
		return *this;//返回自身
	}
	myinteger operator++(int)//int代表一个占位参数,可以用于区分前置和后置递增
	{
		//先记录当时结果
		myinteger temp = *this;
		//后  递增
		m_num++;
		//最后将记录结果做返回
		return temp;
	}
#include<iostream>
#include<string>
using namespace std;
//重载递增运算符
// 
//自定义整型
class myinteger
{
	friend ostream& operator<<(ostream& cout, myinteger myint);
public:
	myinteger()
	{
		m_num = 0;
	}

	//重载++运算符,++a
	myinteger& operator++()//如果返回 值,myint就只能进行一次递增
	{
		m_num++;
		return *this;//返回自身
	}

	//重载++运算符,a++
	//后置递增一定要返回值
	myinteger operator++(int)//int代表一个占位参数,可以用于区分前置和后置递增
	{
		//先记录当时结果
		myinteger temp = *this;
		//后  递增
		m_num++;
		//最后将记录结果做返回
		return temp;
	}
private:
	int m_num;
};
ostream& operator<<(ostream& cout, myinteger myint)
{
	cout << myint.m_num;
	return cout;
}
void test01()
{
	myinteger myint;
	cout << ++myint << endl;
	cout << myint << endl;
}
void test02()
{
	myinteger myint;
	cout << myint++ << endl;;
	cout << myint << endl;
}
int main()
{
	//test01();
	test02();
	system("pause");
	return 0;
}

要注意,前置递增是返回引用,后置递增则返回值。

同时后置递增时,左移运算符重载时要把()里的第二个参数的&去掉。

并且,由于这一点,后置递增不适用于链式编程。


练习了一下递减运算符重载,理解了就很好敲。

#include<iostream>
#include<string>
using namespace std;
class myinteger
{
	friend ostream& operator << (ostream& cout, myinteger myint);
public:
	myinteger()
	{
		m_num = 8;
	}
	myinteger& operator--()
	{
		this->m_num--;
		return *this;//返回自身
	}
	myinteger operator--(int)
	{
		myinteger temp = *this;
		this->m_num--;
		return temp;//返回自身
	}
private:
	int m_num;
};
ostream& operator << (ostream & cout, myinteger  myint)
{
	cout << myint.m_num;
	return cout;
}
void test01()
{
	myinteger myint;
	cout << --myint << endl;
}
void test02()
{
	myinteger myint;
	cout << myint-- << endl;
	cout << myint << endl;
}
int main()
{
	//test01();
	test02();
	system("pause");
	return 0;
}

赋值运算符重载

C++编译器至少给一个类添加4个函数

        1.默认构造函数(无参,函数体为空

        2.默认析构函数(无参,函数体为空

        3.默认拷贝函数,对属性进行值拷贝

        4.赋值运算符 operator=,对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

#include<iostream>
#include<string>
using namespace std;
//赋值运算符重载
class person
{
public:
	person(int age)
	{
		m_age = new int(age);//把数据创建在堆区,并且用指针指向
	}
	//堆区数据需要我们手动开辟,手动释放
	//要提供析构函数,把数据释放干净
	~person()
	{
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
	}
	person& operator=(person&p)
	{
		//应该先判断是否有属性在堆区,要先释放干净,再进行深拷贝
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
		m_age = new int(*p.m_age);//深拷贝
		return *this;
	}
	int *m_age;//把年龄用指针,而其真实数据要开辟到堆区
};

void test01()
{
	person p1(18);
	person p2(20);
	person p3(30);

	p3 = p2 = p1;//赋值运算,简单的浅拷贝
	//指向同一块内存,导致后续内存重复释放,因此我们要利用深拷贝解决浅拷贝带来的问题
	cout << *p1.m_age<<endl;
	cout << *p2.m_age << endl;
	cout << *p3.m_age << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

关系运算符重载

这个比起上面简直是小巫见大巫~~

#include<iostream>
#include<string>
using namespace std;
//关系运算符重载
class person
{
public:

	person(string name, int age)
	{
		m_name = name;
		m_age = age;
	}
	bool operator==(person& p)
	{
		if (this->m_name == p.m_name && this->m_age == p.m_age)
		{
			return true;
		}
		return false;
	}
	string m_name;
	int m_age;
};

void test01()
{
	person p1("胡图图",3);
	person p2("胡英俊", 3);
	if (p1 == p2)
	{
		cout << "same" << endl;
	}
	else cout << "different" << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

函数调用运算符重载

        函数调用运算符()也可以重载

        由于重载后使用的方式非常像函数的调用,因此称为仿函数

        仿函数没有固定写法,非常灵活

#include<iostream>
#include<string>
using namespace std;
//函数调用运算符重载
class myprint
{
public:
	//重载函数调用运算符
	void operator()(string test)
	{
		cout << test << endl;
	}
	
};
class myadd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}

};
void test01()
{
	myprint print;
	print("hello hututu");

	myadd add;
	cout<<add(78, 98)<<endl;

	//匿名函数对象
	cout << myadd()(100, 100) << endl;//即不先创建一个myadd类,匿名对象执行完立即释放
	//通过一个类型和()会创建一个匿名对象
}

int main()
{
	test01();
	system("pause");
	return 0;
}

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

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

相关文章

java堆排序

堆排序是最基本的排序算法&#xff0c;简单来说就是把一堆数据&#xff08;数组&#xff09;分成两个相等的部分&#xff0c;其中一个部分作为数组的开头&#xff0c;另一个部分作为数组的结尾。之后在对这两个相等的部分进行比较&#xff0c;如果在比较之后发现这个数组中有一…

读懂什么是RDMA

一.什么是RDMA 1.RDMA主要体现 2.如何理解RDMA和TCP技术的区别&#xff1f; 3.使用RDMA的好处包括&#xff1a; 二.什么是RoCE&#xff1f; 1. RDMA协议包含: Infiniband&#xff08;IB&#xff09; 2. 为什么RoCE是目前主流的RDMA协议&#xff1f; …

GhostNet

文章目录 相关文章一、轻量化网络结构1. 分组卷积2. 深度可分离卷积 二、GhostNet1. 动机2. Ghost Module 相关文章 https://blog.csdn.net/search_129_hr/article/details/130280697 https://blog.csdn.net/c2250645962/article/details/104601305 一、轻量化网络结构 目的…

信息收集(一)域名信息收集

前言 信息收集也叫做资产收集。信息收集是渗透测试的前期主要工作&#xff0c;是非常重要的环节&#xff0c;收集足够多的信息才能方便接下来的测试&#xff0c;信息收集主要是收集网站的域名信息、子域名信息、目标网站信息、目标网站真实IP、敏感/目录文件、开放端口和中间件…

052:cesium加载网格地图

第052个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载grid地图。一个 ImageryProvider,它在每个具有可控背景和发光的图块上绘制线框网格。 可能对自定义渲染效果或调试地形很有用。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 …

redis 教程 6(Redis 的Pipeline , Lua)

Redis 的Pipeline, Lua PipelinePipeline简介为什么需要PipelinePipeline 性能测试与原生批量命令对比 LuaLua 与事物Lua 的用法Redis 如何管理Lua脚本 Pipeline Pipeline简介 Pipeline&#xff08;流水线&#xff09; 能够将一组redis命令进行组装&#xff0c; 通过一次RTT&…

fmriprep2

一. sub-subXXX文件夹 sub-subXXX.html 二. sub-subXXX文件夹 sub-sub097 / anat / figures / func / log / anat / anat文件夹内文件比较多&#xff0c;文件命名规则遵守BIDS要求( https://bids-specification.readthedocs.io/en/stable/05-derivatives/01-introduction.ht…

【国内chatgpt使用方法合集】

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

2023_4_23_VS下Release怎么打断点进行debug

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

MySQL——流程控制函数

在 MySQL 中&#xff0c;流程控制函数是指可以控制存储过程&#xff08;stored procedure&#xff09;或函数&#xff08;function&#xff09;中执行流程的语句。以下是几个常用的流程控制函数&#xff1a; 1. IF函数 实现IF……ELSE……的效果。 # 如果expr1为true&#x…

深入探究java中的 xxxable和xxxator

前言 相信有一定工作经验的朋友,都见过或者用过xxxable和xxxator ,比如常见的Comparable和Comparator, 还有还有常见并且容易迷糊的Iterable和Iterator, 看这名字,前两个是和比较相关的, 后两个是和迭代相关. 但是命名如此相似的接口, 又有何区别呢?各自的用途又是什么呢? 今…

详解车载设备FOTA测试

作者 | 李伟 上海控安安全测评部总监 来源 | 鉴源实验室 引言&#xff1a;上一篇文章我们以车载Tbox为例介绍了相关的性能测试&#xff08;车载TBOX嵌入式设备软件的性能测试&#xff09;&#xff0c;本篇我们介绍另外一个重要功能的专项测试&#xff1a;OTA&#xff08;Over…

MySQL安装及卸载

安装 mysql现在安装的是5.7.mysql的安装方式有两种: 一种是exe方式 另外一种解压版 这次就使用解压版安装 解压缩到非中文目录 编写配置文件 1) 在安装目录下新建my.ini的配置文件 打开文件后缀和隐藏文件显示 2) 新建文件内编写内容 [Client] port 3306 [mysqld] #设置330…

【移植Ardupilot的日志记录方法到linux上】

移植Ardupilot的日志记录方法到linux上 说明日志结构组成日志写入操作预定义日志项运行时添加日志项的方法 单例测试编译方法查看数据其他 说明 采用二进制文件记录&#xff0c;可在mission planer查看 支持所有数据类型记录精巧移植方便可直接在地面站绘制曲线查看可导出生成…

觉非科技发布:基于BEV的数据闭环融合智驾解决方案

2023年上海车展期间&#xff0c;觉非科技基于BEV的数据闭环融合智能驾驶解决方案正式发布。 该方案可通过量产车BEV的实时感知结果&#xff0c;提供完整的城市Map-lite及Map-free数据闭环融合解决方案&#xff0c;并满足城市NOA、记忆通勤/泊车以及感知大模型训练的需要。 车…

OSPF基础配置实验

目录 一、实验要求与拓扑结构 1、实验要求 2、提前规划好的网段以及拓扑结构如下图 二、实验步骤 1、给各个路由器的每个接口配ip 2、运行ospf协议并划分区域 一、实验要求与拓扑结构 1、实验要求 首先划分区域&#xff0c;蓝色区域为Area 0&#xff0c;黄色区域为Area…

MyBatis(十五)MyBatis的逆向工程

前言、 所谓的逆向工程是&#xff1a;根据数据库表逆向生成Java的pojo类&#xff0c;SqlMapper.xml文件&#xff0c;以及Mapper接口类等。 要完成这个工作&#xff0c;需要借助别人写好的逆向工程插件。 思考&#xff1a;使用这个插件的话&#xff0c;需要给这个插件配置哪些…

基于 TensorRT 使用 python 进行推理优化

文章大纲 简介TensorRT 简介构建测试的conda 环境注意事项TensorRT 安装参考文献与学习路径简介 TensorRT 简介 TensorRT是NVIDIA推出的一个高性能的深度学习推理框架,可以让深度学习模型在NVIDIA GPU上实现低延迟,高吞吐量的部署。TensorRT支持Caffe,TensorFlow,Mxnet,P…

【Python】实战:生成无关联单选问卷 csv《压疮风险评估表》

目录 一、适用场景 二、业务需求 三、Python 文件 &#xff08;1&#xff09;创建文件 &#xff08;2&#xff09;代码示例 四、csv 文件 一、适用场景 实战场景&#xff1a; 问卷全部为单选题问卷问题全部为必填问题之间无关联关系每个问题的答案分数不同根据问卷全部问…

FPGA基于XDMA实现PCIE X8采集AD7606数据 提供工程源码和QT上位机程序和技术支持

1、前言 PCIE&#xff08;PCI Express&#xff09;采用了目前业内流行的点对点串行连接&#xff0c;比起 PCI 以及更早期的计算机总线的共享并行架构&#xff0c;每个设备都有自己的专用连接&#xff0c;不需要向整个总线请求带宽&#xff0c;而且可以把数据传输率提高到一个很…