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

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


文章目录

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


运算符重载

加法运算符重载

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


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

学吧,学无止境,太深了

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

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

相关文章

如何像工程师一样阅读 - 快速阅读技术书籍的9个技巧

0. 目的 在看了 Read Like an Engineer: 9 Tips for Reading Technical Books Fast 之后&#xff0c; 记录一些个人的看法&#xff0c;并在这篇英文文章上作为实验&#xff0c; 记录一下正确的阅读方法。 1. 第一次阅读 1.1 生词表 parcel of the job: 工作中必不可少的部分…

OpenCV-33 开运算和闭运算

目录 一、开运算 二、闭运算 三、形态学梯度 开运算和闭运算都是腐蚀和膨胀的基本应用。 一、开运算 开运算 腐蚀膨胀(腐蚀之后再膨胀) 开运算提供了另一种去除噪声的思路。&#xff08;腐蚀先进行去噪&#xff0c;膨胀再还原图像&#xff09; 通过API --- morphologyE…

面试经典150题——两数之和 II - 输入有序数组

"The only limit to our realization of tomorrow will be our doubts of today." - Franklin D. Roosevelt 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力求解 暴力求解的思路就是通过两次for循环&#xff0c;外层循环遍历整个数组&#xff0c;内层循环遍…

CSP-202109-1-数组推导

CSP-202109-1-数组推导 解题思路 如果 currentValue 与 previousValue 相同&#xff0c;说明这个值不是一个独特的新值&#xff0c;因此只将它加到 sumTotal 上。如果 currentValue 与 previousValue 不相同&#xff0c;说明这是一个新的独特值&#xff0c;因此既将它加到 su…

精简还是全能?如何在 Full 和 Lite 之间做出最佳选择!关于Configuration注解的Full模式与Lite模式(SpringBoot2)

&#x1f3c3;‍♂️ 微信公众号: 朕在debugger© 版权: 本文由【朕在debugger】原创、需要转载请联系博主&#x1f4d5; 如果文章对您有所帮助&#xff0c;欢迎关注、点赞、转发和订阅专栏&#xff01; 前言 关于 Configuration 注解&#xff0c;相信在座的各位 Javaer 都…

【开源】JAVA+Vue.js实现在线课程教学系统

目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2.3 课时管理模块2.4 课程交互模块2.5 系统基础模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示4.1 管理后台4.2 用户网页 五、样例代码5.1 新增课程类型5.2 网站登录5.3 课…

计算机速成课Crash Course - 30. 万维网

今天继续计算机速成课Crash Course的系列讲解。 更多技术文章&#xff0c;全网首发公众号 “摸鱼IT” 锁定 -上午11点 - &#xff0c;感谢大家关注、转发、点赞&#xff01; 计算机速成课Crash Course - 30. 万维网 (qq.com) 30. 万维网 前两集我们深入讨论了电线、信号、交…

【DC渗透系列】DC-4靶场

主机发现 arp-scan -l┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:6b:ed:27, IPv4: 192.168.100.251 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.100.1 00:50:56:c0:00:08 …

Gateway API 实践之(八)FSM Gateway SSL 代理终端与 TLS 上游

FSM Gateway 流量管理策略系列&#xff1a; 故障注入黑白名单访问控制限速重试会话保持健康检查负载均衡算法TLS 上游双向 TLS 网关使用 HTTP 对外与客户端通信&#xff0c;而与上游服务使用 HTTPS 的功能&#xff0c;是一种常见的网络架构模式。在这种模式下&#xff0c;网关…

跟着cherno手搓游戏引擎【23】项目维护、2D引擎之前的一些准备

项目维护&#xff1a; 修改文件结构&#xff1a; 头文件自己改改就好了 创建2DRendererLayer&#xff1a; Sandbox2D.h: #pragma once #include "YOTO.h" class Sandbox2D :public YOTO::Layer {public:Sandbox2D();virtual ~Sandbox2D() default;virtual void O…

阿里云服务器租用价格表_2024一年_1个月_1小时收费价格表

2024年阿里云服务器租用价格表更新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服…

LabVIEW工业监控系统

LabVIEW工业监控系统 介绍了一个基于LabVIEW软件开发的工业监控系统。系统通过虚拟测控技术和先进的数据处理能力&#xff0c;实现对工业过程的高效监控&#xff0c;提升系统的自动化和智能化水平&#xff0c;从而满足现代工业对高效率、高稳定性和低成本的需求。 随着工业自…

时间序列预测 —— DeepAR 模型

时间序列预测 —— DeepAR 模型 DeepAR 模型是一种专门用于处理时间序列概率预测的深度学习模型&#xff0c;它可以自动学习数据中的复杂模式&#xff0c;提高预测的准确性。本文将介绍 DeepAR 模型的理论基础、优缺点&#xff0c;并通过 Python 实现单步预测和多步预测的完整…

51单片机编程应用(C语言):串口通信

目录 通信的基本概念和种类 1.1串行通信与并行通信 ​编辑 1.2同步通信与异步通信 1.3单工&#xff0c;半双工&#xff0c;全双工 1.4通信速率 二、波特率和比特率的关系 串口通信简介&#xff1a; 1.接口标准 RS-232 2、D型9针接口定义 3.通信协议&#xff1a; …

金和OA C6 RssModulesHttp.aspx SQL注入漏洞复现

0x01 产品简介 金和网络是专业信息化服务商,为城市监管部门提供了互联网+监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 0x02 漏洞概述 金和OA C6 RssModulesHttp.aspx接口处存在SQL注入漏洞,攻击者除了可以利用 SQL 注入…

018 Linux

文章目录 操作系统定义分类Linux系统构成 Linux文件系统Linux常用命令基础操作命令文件操作压缩解压权限管理显示展示命令其他命令 vi编译器操作使用 添加用户基本概念用户管理命令 ubuntu软件安装ssh服务终端启动Python服务 操作系统 定义 操作系统是管理计算机硬件与软件资…

【Linux系统学习】 4.Linux实用操作 上

Linux实用操作 1.各类小技巧&#xff08;快捷键&#xff09; 1.1 ctrl c 强制停止 Linux某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键ctrl c 命令输入错误&#xff0c;也可以通过快捷键ctrl c&#xff0c;退出当前输入&#xff0c;重新输入 1…

前端JavaScript篇之如何获得对象非原型链上的属性?

目录 如何获得对象非原型链上的属性&#xff1f; 如何获得对象非原型链上的属性&#xff1f; 要获取对象上非原型链上的属性&#xff0c;可以使用 hasOwnProperty() 方法。这个方法是 JavaScript 内置的对象方法&#xff0c;用于检查一个对象是否包含指定名称的属性&#xff0…

数字孪生与智慧园区的融合:打造未来产业生态的新篇章

随着科技的飞速发展&#xff0c;数字孪生和智慧园区已经成为当今社会发展的重要趋势。数字孪生技术为物理世界的对象提供了数字化的复制体&#xff0c;而智慧园区则通过各种信息技术手段实现园区的智能化管理。二者的融合&#xff0c;将为未来产业生态的发展开辟新的篇章。 一…

大华智慧园区综合管理平台 deleteFtp RCE漏洞复现

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