【C++第二阶段】运算符重载-【+】【cout】【++|--】

news2025/1/18 11:53:38

你好你好!
以下内容仅为当前认识,可能有不足之处,欢迎讨论!


文章目录

  • 运算符重载
    • 加法运算符重载
    • 重载左移运算符
    • 递增|减运算符重载


运算符重载

加法运算符重载

What

普通的加减乘除,只能应付C++中已给定的数据类型的运算,对其重载,使得满足多种多样的运算。

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

注意

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

②不要滥用运算符重载。

对于①,基本的运算符运算不改变,int+int = int , float + float = float.

对于②,重写相加,就写相加,名副其实。如果重写了加法运算符,里面却写➖或者×÷,代码可读性会变差。

代码

成员函数重载加法运算符

#include<iostream>
#include<string>
using namespace std;
void test_0208_0();

class Person {
public:
	float person_height;
	int person_weight;
	Person operator+(Person& person);//成员函数运算符重载
};

Person Person::operator+(Person& person) {
	Person temp;
	temp.person_height = this->person_height + person.person_height;
	temp.person_weight = this->person_weight + person.person_weight;
	return temp;
}

void test_0208_0() {
	Person per, son , person_sum;
	per.person_weight = 70;
	per.person_height = 1.83;

	son.person_weight = 60;
	son.person_height = 1.83;

	person_sum = per + son;
	//成员函数重载加法运算符相当于:
	//person_sum = per.operator+(son);

	cout << "person sum 总身高为:" << person_sum.person_height << "." << endl;
	cout << "person sum 总体重为:" << person_sum.person_weight << "." << endl;

}


int main() {
	cout << "hello world !" << endl;
	test_0208_0();
    
    system("pause");
    return 0;
}

运行结果

image-20240208162939715

可以看到,将两人的身高和体重在加法运算符重载之后进行了求和。

全局函数重载加法运算符

#include<iostream>
#include<string>
using namespace std;
void test_0208_0();
void test_0208_1();
void test_0208_2();

class Person {
public:
	float person_height;
	int person_weight;
	Person operator+(Person& person);//成员函数运算符重载
};

Person operator+(Person& per, Person& son) {
	Person temp;
	temp.person_height = per.person_height + son.person_height;
	temp.person_weight = per.person_weight + son.person_weight;
	return temp;
}

void test_0208_0() {
	Person per, son , person_sum;
	per.person_weight = 70;
	per.person_height = 1.83;

	son.person_weight = 60;
	son.person_height = 1.83;

	person_sum = per + son;

	//全局成员函数重载加法运算符相当于:
	//person_sum = operator+(per , son);

	cout << "person sum 总身高为:" << person_sum.person_height << "." << endl;
	cout << "person sum 总体重为:" << person_sum.person_weight << "." << endl;

}

int main() {
	cout << "hello world !" << endl;
	test_0208_0();
    system("pause");
    return 0;
}

运行结果

image-20240208162939715

重载左移运算符

场景:

想要cout直接输出类里面的各种属性,简单地使用``cout<<person<<endl;会报错。需要重写<<`运算符。

How

考虑到加法运算符的重载,使用成员函数重载左移运算符。

但此时,有两个问题:①函数返回值是什么数据类型?②如何调用?

回答问题①

通过点击cout右键后,选择转到定义。

image-20240208171255369

接着出现:

image-20240208171337955

可以看到,cout属于的类是ostream输出流对象。

所以,如果想链式调用函数,可以将返回值设置为ostream。同时,只能用引用方式传递,因为全局只能有一个。

成员函数重载左移运算符:

#include<iostream>
#include<string>
using namespace std;
void test_0208_1();

class Person {
private :
	int weight;
	double height;
public:
	Person(int weight, double height);
	void operator<<(ostream& cout);
};

Person::Person(int weight, double height) {
	this->weight = weight;
	this->height = height;
}

void Person::operator<<(ostream &cout) {
	cout << "person 的身高为:" << this->height << "." << endl;
	cout << "person 的体重为:" << this->weight << "." << endl;

}

void test_0208_1() {
	int weight = 70;
	double height = 1.85;
	Person person(weight, height);
	person << cout;
	//等价于
	//person.operator<<(cout);
}


int main() {
	cout << "hello world !" << endl;
	test_0208_1();
	system("pause");
	return 0;
	}
	

运行结果为:

image-20240208172157591

但是不想要person<<cout;,或者person.operator<<(cout);这样的写作方式,而是要重载后的输出方式cout<<person<<endl;

如果现在加上<<endl;则后面会报错。

image-20240208172334418

image-20240208172322256

这个方式实际上是链式调用函数出错出现的问题,可以更改返回值为对应的ostream &引用来解决。

比如,以上代码中的成员函数改为:

class Person {

private :
	int weight;
	double height;
public:
	Person(int weight, double height);
    //返回值由void 改为ostream &
	ostream& operator<<(ostream& cout);
};

Person::Person(int weight, double height) {
	this->weight = weight;
	this->height = height;
}

//返回值由void 改为ostream
ostream& Person::operator<<(ostream &cout) {
	cout << "person 的身高为:" << this->height << "." << endl;
	cout << "person 的体重为:" << this->weight << "." << endl;
	return cout;
}


void test_0208_1() {
	int weight = 70;
	double height = 1.85;
	Person person(weight, height);
	person << cout<<endl;//添加endl后不会报错
	//等价于
	//person.operator<<(cout);
}

运行结果为

image-20240208172548485

但仍没有解决想要使用cout<<person<<endl;进行输出的问题。

原因在于,如果用成员函数重载,则person只能出现在左侧,cout出现在右侧。所以,更换为使用全局函数。

全局函数重载左移运算符

#include<iostream>
#include<string>
using namespace std;
void test_0208_0();
void test_0208_1();
void test_0208_2();

class Person {
    //要注意添加全局函数为类的友元,否则私有成员属性无法访问。
	friend ostream& operator<<(ostream& out, Person &person);
private :
	int weight;
	double height;
public:
	Person(int weight, double height);
	//void operator<<(ostream& cout);
};

Person::Person(int weight, double height) {
	this->weight = weight;
	this->height = height;
}

ostream& operator<<(ostream& out,Person& person) {
    //这里的out是引用,就是别名。
	out << "person 的身高为:" << person.height << "." << endl;
	out << "person 的身高为:" << person.weight << "." << endl;
	return out;
}

void test_0208_1() {
	int weight = 70;
	double height = 1.85;
	Person person(weight, height);
	cout << person << endl;
	//全局函数重载等价于
	//operator<<(cout, person);
}

int main() {
	cout << "hello world !" << endl;
	test_0208_1();
	system("pause");
    return 0;
}

operator<<(cout,person)运行结果:

image-20240208174206491

递增|减运算符重载

目的

想要达到一个自定义的整数类实现前置递增或后置递增的操作。

How

分为前置递增运算符和后置递增运算符。

对于前置递增运算符,返回值需要是MyInt类型的,因为cout已经重写,所以最好是这种类型。

返回值是指针,因为是对于当前的类进行的加减操作。

对于后置递增运算符,需要在参数中写入占位符,编译器明白这是后置运算符。

#include<iostream>
#include<string>
using namespace std;
void test_0208_1();
void test_0208_2();
void test_0208_3();
void test_0208_4();
void test_0208_5();

class MyInt {
	friend ostream& operator<<(ostream& print, MyInt my_int);

private:
	int num;

public:
	MyInt() {
		num = 0;
	}
	MyInt(int number) {
		num = number;
	}

	//成员函数-前置递增函数
	//返回值为什么是数字,因为想要它实现前置递增的功能,让cout输出,但是cout不知道怎么输出void类型的变量
	//所以需要返回值
	//需要返回自身,this是指针,解引用之后才是自身。
	//至于返回值,则是一个引用


	//MyInt& operater++() {
		//this->num++;
		//return *this;
	//}

	//若返回值,则以下为返回值的测试案例
	MyInt& operator++() {
		this->num++;
		return *this;
	}


	//成员函数-后置递增函数
	MyInt& operator++(int) {
		static MyInt temp = *this;
		this->num++;
		return temp;
	}

	MyInt& operator--() {
		--this->num;
		return *this;
	}

	MyInt& operator--(int) {
		static MyInt temp = *this;
		this->num--;
		return temp;
	}
	
	
};

ostream& operator<<(ostream& print, MyInt my_int) {
	cout << my_int.num;
	return print;
}


void test_0208_2() {
	cout << "==========test_0208_2()==========" << endl;
	MyInt my_int(20);
	cout <<"my_int \t==>" << my_int << endl;
	cout << "========\t" << endl;
	cout << "++my_int ==>" << ++my_int << endl;
	cout << "my_int \t==>" << my_int << endl;
	//使用返回值的前置递增函数,两次递增后,新的值为新的随机值,而不是my_int
	//对于my_int为什么是11,是因为只有第一个作为存储值留下来了
	cout << "========\t" << endl;
	cout << "++(++my_int)==>" << ++(++my_int) << endl;
	cout <<"my_int \t==>" << my_int << endl;
	cout << "==========test_0208_2()==========\n" << endl;

}

void test_0208_3() {
	cout << "==========test_0208_3()==========" << endl;
	MyInt my_int = 30;
	cout << "原始的my_int = " << my_int << "." << endl;
	cout << "my_int ++ 后,my_int = " << my_int++ << "." << endl;
	cout << "现在的my_int = " << my_int << "." << endl;
	cout << "==========test_0208_3()==========\n" << endl;
}


void test_0208_4() {
	cout << "==========test_0208_4()==========" << endl;
	MyInt my_int(40);
	cout << "my_int \t==>" << my_int << endl;
	cout << "========\t" << endl;
	cout << "--my_int ==>" << --my_int << endl;
	cout << "my_int \t==>" << my_int << endl;
	//使用返回值的前置递增函数,两次递增后,新的值为新的随机值,而不是my_int
	//对于my_int为什么是11,是因为只有第一个作为存储值留下来了
	cout << "========\t" << endl;
	cout << "--(--my_int)==>" << --(--my_int) << endl;
	cout << "my_int \t==>" << my_int << endl;
	cout << "==========test_0208_4()==========\n" << endl;

}

void test_0208_5() {
	cout << "==========test_0208_5()==========" << endl;
	MyInt my_int = 50;
	cout << "原始的my_int = " << my_int << "." << endl;
	cout << "my_int -- 后,my_int = " << my_int-- << "." << endl;
	cout << "现在的my_int = " << my_int << "." << endl;
	cout << "==========test_0208_5()==========\n" << endl;
}

int main() {
	cout << "hello world !" << endl;
	test_0208_5();
	test_0208_4();
	test_0208_3();
	test_0208_2();
    system("pause");
    return 0;
}

运行结果

image-20240209010008149


以上是我的学习笔记,希望对你有所帮助!
如有不当之处欢迎指出!谢谢!

学吧,学无止境,太深了

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

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

相关文章

SFML(1) | 自由落体小球

SFML(1) | 自由落体小球 文章目录 SFML(1) | 自由落体小球1. 目的2. SFML 适合做图形显示的理由3. 使用 SFML - 构建阶段4. 使用 SFML - C 代码5. 运行效果6. 总结7. References 1. 目的 通过一些简单的例子&#xff08;2D小游戏的基础代码片段&#xff09;&#xff0c; 来学习…

Python 小白的 Leetcode Daily Challenge 刷题计划 - 20240209(除夕)

368. Largest Divisible Subset 难度&#xff1a;Medium 动态规划 方案还原 Yesterdays Daily Challenge can be reduced to the problem of shortest path in an unweighted graph while todays daily challenge can be reduced to the problem of longest path in an unwe…

互联网加竞赛 基于深度学习的目标检测算法

文章目录 1 简介2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 1 简介 &#x1f5…

害怕跟别人进行社交,怎么办?

前几天&#xff0c;跟一位朋友&#xff0c;小聚了一下。 这位朋友&#xff0c;在一家大型 IT 公司里当技术主管。收入不低&#xff0c;烟酒不沾&#xff0c;常常健身&#xff0c;外型不错&#xff0c;为人也踏实可靠。除了有一点技术宅的死板之外&#xff0c;可以说是非常理想的…

小项目:蓝牙模块点亮RGB三色灯

在之前的教程中&#xff0c;我们学习了蓝牙模块的原理&#xff0c;并动手写了驱动&#xff0c;实现了串口的接收和发送。本次我们就来教大家如何使用蓝牙串口控制灯。这是一个简单的示例&#xff0c;展示了如何将蓝牙通信与硬件控制相结合&#xff0c;实现远程控制的功能。你也…

微软Windows生态是怎么打造成功的?

&#xff08;1&#xff09;2015年Windows10&#xff1a;兼容性 我不得不再次佩服一下微软&#xff0c;Windows10是2015年出品的&#xff0c;但是仍然能正常运行绝大多数的Windows95软件&#xff0c;不用做任何的适配修改&#xff0c;连重新编译都不用&#xff0c;运行照样正常。…

AcWing 1224 交换瓶子(简单图论)

[题目概述] 有 N 个瓶子&#xff0c;编号 1∼N&#xff0c;放在架子上。 比如有 5 个瓶子&#xff1a; 2 1 3 5 4 要求每次拿起 2 个瓶子&#xff0c;交换它们的位置。 经过若干次后&#xff0c;使得瓶子的序号为&#xff1a; 1 2 3 4 5 对于这么简单的情况&#xff0c;显然&a…

mysql8.0 正值表达式Regular expressions (sample database classicmodels _No.5)

mysql8.0 正值表达式Regular expressions 准备工作&#xff0c;可以去下载 classicmodels 数据库资源如下 [ 点击&#xff1a;classicmodels] (https://download.csdn.net/download/tomxjc/88685970) 也可以去我的博客资源下载 https://download.csdn.net/download/tomxjc/8…

Eclipse导入maven项目或者创建maven项目时,报错Could not calculate build plan: Plugin

问题&#xff1a;Eclipse导入maven项目或者创建maven项目时,报错Could not calculate build plan: Plugin 1.上述问题大概是项目不能加载此maven插件&#xff0c;在pom文件中添加依赖项 <dependency><groupId>org.apache.maven.plugins</groupId><artifa…

JetpackCompose之状态管理

JetPack Compose系列&#xff08;13&#xff09;—状态管理 State 即&#xff0c;状态。官方的解释是&#xff1a; State in an application is any value that can change over time. And ****event can notify a part of a program that something has happened. 可以这样…

发廊理发店微信小程序展示下单前端静态模板源码

模板描述&#xff1a;剪发小程序前端源码&#xff0c;一共五个页面&#xff0c;包括店铺、理发师、订单、我的等页面 注&#xff1a;该源码是前端静态模板源码&#xff0c;没有后台和API接口

代码随想录算法训练营第四十六天(动态规划篇)|01背包(滚动数组方法)

01背包&#xff08;滚动数组方法&#xff09; 学习资料&#xff1a;代码随想录 (programmercarl.com) 题目链接&#xff08;和上次一样&#xff09;&#xff1a;题目页面 (kamacoder.com) 思路 使用一维滚动数组代替二维数组。二维数组的解法记录在&#xff1a;代码随想录算…

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 题目示例 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&a…

嵌入式学习之Linux入门篇笔记——18,makefile基本语法(下)

配套视频学习链接&#xff1a;http://【【北京迅为】嵌入式学习之Linux入门篇】 https://www.bilibili.com/video/BV1M7411m7wT/?p4&share_sourcecopy_web&vd_sourcea0ef2c4953d33a9260910aaea45eaec8 1.wildcard 函数 格式&#xff1a;$&#xff08;wildcard PAT…

Ivanti Pulse Connect Secure VPN SSRF(CVE-2023-46805)漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

maven-install-plugin:2.4:install (default-cli) on project ability-dispatch:

IDEA&#xff0c;instal时报错 &#xff0c;错误 信息如下&#xff1a; Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.4:install (default-cli) on project ability-dispatch: The packaging for this project did not assign a file to the buil…

使用 devc++ 开发 easyx 实现 Direct2D 交互

代码为 codebus 另一先生的 文案 EasyX 的三种绘图抗锯齿方法 - CodeBus 这里移植到 devc 移植操作如下&#xff1a; 调用dev 的链接库方式&#xff1a; project -> project option -> 如图所示 稍作修改的代码。 #include <graphics.h> #include <d2d1.…

Onerugged三防平板厂家丨三年质保承诺丨三防平板PAD

行业领先产品——Onerugged三防平板。凭借着十年的经验&#xff0c;我们深知终端设备在各个行业中的重要性&#xff0c;因此致力于为用户提供高可靠性的解决方案。 Onerugged三防平板以其卓越的性能和全方位的保护功能&#xff0c;在市场上脱颖而出。首先&#xff0c;它拥有IP…

路由引入路由过滤排错

目录 排错网络拓扑图 排错需求 故障排错 故障一 故障二 故障三 排错网络拓扑图 排错需求 按照图示配置 IP 地址&#xff0c;总部和分支 A、分支 B 各自使用 loopback 口模拟业务网段公司业务流分为 A 流和 B 流&#xff0c;网段如图所示总部内部配置 OSPF 互通&#xff0…

Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号

Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号 code review! 文章目录 Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号1.expect2.bash 1.expect 在Expect脚本中&#xff0c;你可以使用expect来监听程序输出&#xff0c;…