浅谈C++|运算符重载

news2025/1/16 1:07:30


重载原因

C++ 中的运算符重载是一种特性,允许程序员定义自定义类类型的运算符操作。通过运算符重载,可以对类对象执行类似于内置类型的操作,例如加法、减法、乘法等。

运算符重载通过定义特定的成员函数或非成员函数来实现。成员函数的运算符重载为类的成员函数,且至少需要一个类对象作为操作数。而非成员函数的运算符重载则是独立于类的函数,其参数可以是类对象、指针或者引用。

运算符重载使用特定的语法,以便将运算符关联到相应的函数实现。例如,对于双目运算符(如+、-、*),可以通过重载成员函数或非成员函数的方式定义其操作。其中,成员函数的运算符重载使用成员函数的方式进行调用,而非成员函数的运算符重载则使用运算符的左侧对象作为第一个参数。

运算符重载提供了方便和直观的方式来执行类对象之间的操作。它可以使代码更具可读性,并提供更自然的语义,使得类的行为更接近内置类型。

然而,运算符重载也需要谨慎使用。过度使用运算符重载可能会导致代码可读性下降,使得代码难以理解和维护。因此,在进行运算符重载时,应注意遵循适当的语义和约定,并且避免使用过于复杂或混淆的运算符重载实现。

总结来说,C++ 中的运算符重载是一种强大的特性,允许程序员定义自定义类类型的运算符操作。通过合理和适度地使用运算符重载,可以提高代码的可读性和可维护性,使类对象的操作更加自然和直观。

一.加号运算符重载

对于内置的数据类型的表达式的运算符是不可能改变的

不要滥用运算符重载 

1.1成员函数实现

成员函数实现时,即使成员函数是私有变量,也是可以实现运算符重载的,并且支持函数重载。

代码: 

#include <iostream>
using namespace std;
class person {
friend void fun();
private:
	int age;
	int year;
public:
	person(int age, int year) :age(age), year(year) {}
	person(){}
	person operator+(person& p) {
		person m;
		m.age = this->age + p.age;
		m.year = this->year + p.year;
		return m;
	}
};
void fun() {
	person a(10, 90);
	person b(34, 89);
	person c = a + b;
	cout << c.age << ' ' << c.year << endl;
}
int main() {
	fun();
	return 0;
}

此时person c = a + b本质是person c=a.operator+(b);

person d = a + 10本质是person d=a.operator+(10);

 2.2全局函数实现

全局函数实现时,重载运算符函数不能直接访问私有成员变量,需要在类中声明友元。

代码: 

#include <iostream>
using namespace std;
class person {
friend void fun();   //设置全局函数是友元
friend person operator+(person& p1, person& p2);
friend person operator+(int p, person& p1);
private:
	int age;
	int year;
public:
	person(int age, int year) :age(age), year(year) {}
	person(){}
};

person operator+(person& p1,person& p2) {
	person m;
	m.age =p1.age + p2.age;
	m.year =p1.age + p2.year;
	return m;
}

person operator+(int p,person& p1) {   //函数重载
	person m;
	m.age = p1.age + p;
	m.year = p1.year + p;
	return m;
}
void fun() {
	person a(10, 90);
	person b(34, 89);
	person c = a + b;
	person d = 10+ a;  
	cout << c.age << ' ' << c.year << endl;
	cout << d.age << ' ' << d.year << endl;
}
int main() {
	fun();
	return 0;
}

此时,person c = a + b;  本质是person c =operator+(a,b);
           person d = 10+ a;  本质是person d =operator+(10,a);

 二.左移运算符重载

2.1成员函数实现

成员函数只能实现p<<cout......类型,cout不能放在左边;

 代码:

#include <iostream>
using namespace std;
class person {
private:
	int age;
	int year;
public:
	person(int age,int year):age(age),year(year){}
	person() {};
	//返回ostream&是为了链式调用
	ostream& operator<<(ostream& cout) {
		cout << this->age << ' ' << this->year;
		return cout;
	}
};
void fun() {
	person p(23,78);
	p << cout << "成功" << endl;
	//本质p.operator<<(cout)<<"成功"<<endl;
}
int main() {
	fun();
	return 0;
}

p << cout << "成功" << endl的本质是p.operator<<(cout)<<"成功"<<endl;

 2.2全局函数实现

全局函数可以实现cout在类的左边,也可以实现在类的右边

代码:

#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& cout, person& p);
private:
	int age;
	int year;
public:
	person(int age, int year) :age(age), year(year) {}
	person() {};
	//返回ostream&是为了链式调用
};
ostream& operator<<(ostream& cout,person& p) {
	cout << p.age << ' ' << p.year;
	return cout;
}
void fun() {
	person p(23, 78);
	cout<< p << "成功" << endl;
	//本质p.operator<<(cout)<<"成功"<<endl;
	//本质operator<<(cout,p)<<"成功"<<endl;
}
int main() {
	fun();
	return 0;
}

三.++运算符重载

前置++重载不用参数,返回值是引用类型,后置++重载要int占位参数,返回值是值。

 31.前置++

代码: 

#include <iostream>
using namespace std;
class myint {
friend ostream& operator<<(ostream& cout, myint& p);
public:
	myint(int age,int year):age(age),year(year){}
	myint(){}
	//重载前置++,返回*this也是为了链式调用
	myint& operator++() {
		this->age++;
		return *this;
	}
private:
	int age;
	int year;
};
//重载<<运算符,注意是ostream& cout,是引用类型
ostream& operator<<(ostream& cout, myint &p) {
	cout << p.age << ' ' << p.year;
	return cout;
}
void fun() {
	myint p(10, 20);
	cout << ++(++p) << endl;;
}
int main() {
	fun();
	return 0;
}

 返回追是引用类型,如果返回普通值的话,只能自增一次,第二次只是改变副本。

3.2后置 ++

代码:

#include <iostream>
using namespace std;
class myint {
friend ostream& operator<<(ostream& cout, myint& p);
friend void fun1();
public:
	myint(int age,int year):age(age),year(year){}
	myint(){}
	//重载前置++,返回*this也是为了链式调用
	myint& operator++() {
		this->age++;
		return *this;
	}
	//重置后置++,返回之前副本。
	myint operator++(int) {
		myint m = *this;
		this->age++;
		return m;
	}
private:
	int age;
	int year;
};
//重载<<运算符,注意是ostream& cout,是引用类型
ostream& operator<<(ostream& cout, myint &p) {
	cout << p.age << ' ' << p.year;
	return cout;
}
void fun() {
	myint p(10, 20);
	cout << ++(++p)<<endl;;
}
void fun1() {
	myint p(10, 20);
	cout << (p++).age << endl;
	cout << p.age << endl;
}
int main() {
	fun1();
	return 0;
}

后置++用int占位参数,用来区分和前置++的区别,并且要注意,返回的是值类型

 四.赋值运算符重载

 在实例化类的对象时,会自动创建一个operator=函数,不过此时是浅拷贝,当遇到建立到堆上的数据类型时。调用赋值运算符会报错。此时需要重载赋值运算符,将浅拷贝改为深拷贝。

代码:

#include <iostream>
using namespace std;
class person {
public:
	int* age;
	int year;
	//有参构造,在堆区开辟
	person(int age, int year) {
		this->age = new int(age);
		this->year = year;
	}
	//深拷贝
	person(const person& p) {
		year = p.year;
		age = new int(*p.age);
		
	}

	//返回值是引用类型,链式调用
	person& operator=(const person& p) {
		if (this->age != NULL) {
			delete age;
			age = NULL;
		}
		year = p.year;
		//深拷贝
		age = new int(*p.age);   
		return *this;
	}

	~person() {
		if (this->age != NULL) {
			delete age;
			age = NULL;
		}
	}
};
void fun() {
	person p1(43, 78);
	person p2(4, 7);
	person p3(89, 90);
	p3=p2 = p1;
	cout << *p2.age << ' ' << p2.year << endl;
	cout << *p3.age << ' ' << p3.year << endl;
}
int main() {
	fun();
	return 0;
}

p3=p2 = p1的本质是p3.operator=(p2.operator=(p1))

 五.函数调用运算符重载

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

·由于重载后使用的方式非常像函数的调用,因此称为仿函数,仿函数没有固定写法,非常灵活

 代码:


#include <iostream>
using namespace std;
class person {
public:
	int age;
	person(int age) {
		this->age = age;
	}
	person(){}
	void operator()(string name) {
		cout << name << endl;
	}
	void operator()() {
		cout << "年龄是:" << age << endl;
	}
};
void fun() {
	person p1(10);
	person p2(20);
	p1("name_name");
	//匿名对象
	person()("匿名调用");
	p1();
	p2();
}
int main() {
	fun();
	return 0;
}

六.关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

 代码:

#include <iostream>
using namespace std;
class person {
public:
	int age;
	string name;
	person(int age, string name) :age(age), name(name) {}
	//重载==号,函数设置为常函数是为了防止误操作
	bool operator==(const person& p)  const{
		if (age == p.age && name == p.name) {
			return true;
		}
		return false;
	}
	//重载!=号
	bool operator!=(const person& p) const  {
		if (age == p.age && name == p.name) {
			return false;
		}
		return true;
	}
	//重载>号
	bool operator>(const person& p) const {
		if (age == p.age) {
			return name > p.name;
		}
		else {
			return age > p.age;
		}
	}

};
void fun() {
	person p1(40, "tom");
	person p2(10, "aom");
	if (p1 == p2) {
		cout << "p1=p2" << endl;
	}
	else {
		cout << "p1!=p2" << endl;
	}

	if (p1 != p2) {
		cout << "p1!=p2" << endl;
	}
	else {
		cout << "p1==p2" << endl;
	}

	if (p1 > p2) {
		cout << "p1 > p2" << endl;
	}
	else {
		cout << "p1 <= p2" << endl;
	}
}
int main() {
	fun();
	return 0;
}

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

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

相关文章

html怎么设置按钮返回顶部

在 HTML 中&#xff0c;我们可以通过一些代码和 CSS 样式来创建一个这样的按钮。 <button onclick"topFunction()" id"myBtn">返回顶部</button> <style> #myBtn { display: none; position: fixed; bottom: 20px; right: 30px; z-inde…

高性能 Python 编译器 -- Codon

众所周知&#xff0c;Python 是一门简单易学、具有强大功能的编程语言&#xff0c;在各种用户使用统计榜单中总是名列前茅。相应地&#xff0c;围绕 Python&#xff0c;研究者开发了各种便捷工具&#xff0c;以更好的服务于这门语言。 编译器充当着高级语言与机器之间的翻译官&…

一封来自江苏省电力设计院的表扬信

近日&#xff0c;中新赛克海睿思收到了一封来自江苏省电力设计院公司&#xff08;以下简称“江苏院”&#xff09;的表扬信。 海睿思与江苏院自达成合作以来&#xff0c;双方团队经过共同努力&#xff0c;克服了项目交付过程中的诸多困难。不仅通过数据工程的整体咨询帮助江苏院…

pt26django教程

admin 后台数据库管理 django 提供了比较完善的后台管理数据库的接口&#xff0c;可供开发过程中调用和测试使用 django 会搜集所有已注册的模型类&#xff0c;为这些模型类提拱数据管理界面&#xff0c;供开发者使用 创建后台管理帐号: [rootvm mysite2]# python3 manage.…

什么是函数重载?作用是什么?如何使用?

函数重载是指在同一个作用域内&#xff0c;允许存在多个同名函数&#xff0c;但这些函数的参数列表必须不同。根据传入的参数类型、数量或顺序的不同&#xff0c;编译器可以区分调用哪个函数。 函数重载的作用主要有以下几点&#xff1a; 提高代码的可读性和可维护性&#xff…

openlayers-17-卷帘对比

实现卷帘对比功能&#xff0c;没有进一步测试版本兼容问题&#xff0c;不错从ol的官网来看&#xff0c;ol6之前的版本的示例与ol6及其之后的版本示例并不相同 ol5 示例https://openlayers.org/en/v5.3.0/examples/layer-swipe.html?qlayerswipeol6示例 https://openlayers.org…

GIS跟踪监管系统

GIS跟踪监管系统 系统架构功能模块1. 基本功能2. 仓库管理3. 物资查询 系统采用B/S架构&#xff0c;前端使用的技术为HTMLCSSJavaScript&#xff08;Leaflet、jQuery、bootstrap等&#xff09;&#xff0c;后台采用.NET框架。 系统架构 救援物资跟踪监管系统的架构如图所示&am…

Matplotlib入门

基本使用 基本用法 import matplotlib.pyplot as plt import numpy as npxnp.linspace(-1,1,50) y2*x1plt.figure()#定义一个图像窗口 plt.plot(x,y)#画&#xff08;x&#xff0c;y&#xff09;曲线 plt.show()#显示图像figure图像 import matplotlib.pyplot as plt import …

nat的基础配置(动态nat,nat server)

目录 1.静态nat 2.动态nat &#xff08;1&#xff09;配置公网地址池 &#xff08;2&#xff09;配置acl&#xff0c;匹配做nat转换的源 &#xff08;3&#xff09;将源转换为公网地址&#xff0c;其中no-pat表示不做端口转化&#xff0c;只做一对一的地址转换 3.nat ser…

《向量数据库指南》——向量数据库Milvus Cloud为什么选择开源?

开源对我们来说是一种信仰。从最早开始研发向量数据库的时候&#xff0c;我们就相信应该让更多人了解并使用优秀的技术&#xff0c;这是我们选择做开源的原因。 无论是在 AI 领域还是其他领域&#xff0c;我们希望技术不会被少数大公司垄断。在向量数据库问世之前&#xff0c;阿…

python:优化一EXCEL统计用类封装一下

# encoding: utf-8 # 版权所有 2023 涂聚文有限公司 # 许可信息查看&#xff1a; # 描述&#xff1a; # Author : geovindu,Geovin Du 涂聚文. # IDE : PyCharm 2023.1 python 311 # Datetime : 2023/9/17 5:40 # User : geovindu # Product : PyCharm # Proj…

JSON和全局异常处理

目录 1️⃣JSON 一、什么是json&#xff1f; 二、与javascript的关系 三、语法格式 四、注意事项 五、总结 六&#xff0c;使用json 1导入pom.xml依赖 2.配置spring-mvc.xml 3. ResponseBody注解使用 创建一个web层控制器 编写ClazzBiz 实现接口 测试&#xff1a; …

C#,数值计算——Hashfn2的计算方法与源程序

1 文本格式 using System; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer { public class Hashfn2 { private static ulong[] hashfn_tab { get; set; } new ulong[256]; private ulong h { get; set;…

【2023年11月第四版教材】第13章《资源管理》(第三部分)

第13章《资源管理》&#xff08;第部分&#xff09; 4 管理过程4.1 数据表现★★★4.2 资源管理计划★★★4.2 团队章程★★★ 5 估算活动资源 4 管理过程 组过程输入工具和技术输出规划1.规划资源管理1.项目章程2.项目管理计划&#xff08;质量管理计划、范围基准&#xff09…

elasticsearch5-RestAPI操作

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

Python 布尔类型和比较运算符

视频版教程 Python3零基础7天入门实战视频教程 布尔( bool&#xff09;表达现实生活中的逻辑&#xff0c;即真和假&#xff0c;True表示真&#xff0c;False表示假。 实例&#xff1a; # 布尔类型定义 b1 True b2 False print(f"b1{b1},类型是{type(b1)}") prin…

分类预测 | MATLAB实现WOA-CNN-LSTM-Attention数据分类预测

分类预测 | MATLAB实现WOA-CNN-LSTM-Attention数据分类预测 目录 分类预测 | MATLAB实现WOA-CNN-LSTM-Attention数据分类预测分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现WOA-CNN-LSTM-Attention数据分类预测&#xff0c;运行环境Matlab2021b及以…

Vue3+Ts+Vite项目(第十五篇)——tailwindcss安装及使用详解,css原子化如何实现

文章目录 一、装包二、初始化2.1 终端执行如下命令2.2 postcss.config.js 文件中2.3 tailwind.config.js 文件中 三、样式文件3.1 新建 tailwind.css 文件3.2 main.ts 中引入 四、使用4.1 写入类名即可4.2 简单讲解 五、插件5.1 安装 Tailwind CSS IntelliSense5.2 使用效果 六…

系统架构设计高级技能 · 构件与中间件技术

点击进入系列文章目录 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 系统架构设计高级技能 构件与中间件技术 一、构件的定义二、构件系统架构特性三…

Vue ——09、路由模式,404和路由勾子

路由嵌套&#xff0c;参数传递及重定向 一、路由模式&#xff08;有#号&#xff0c;跟没#号&#xff09;二、404三、路由勾子四、在钩子函数中使用异步请求————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶…