news 2026/7/24 20:46:56

类中的流操作符的重载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
类中的流操作符的重载

目录

摘要:

一:理解cout的本质

二:<<操作符的重载

问题1:参数颠倒

问题2:无法访问私有成员变量

问题3:无法连续使用<<

问题4:最终版本

三:>>操作符的重载

四:细节补充


摘要:

本文实现类中的流操作符的重载,也就是>>和<<的重载,我们只需理解<<的重载就可以同理理解>>的重载.....


一:理解cout的本质

首先我们要理解cout这个东西,因为我们使用<<是和cout一起使用的!

https://legacy.cplusplus.com/reference/iostream/cout/?kw=cout

以上官网中对cout的描述如下:

解释:

我们只用知道以下即可:

①:cout 是类 ostream 的对象,它是一个全局的,已经定义好的 ostream 类的对象

②:我们cout<<的形式写入数据时,cout是作为对象调用<<这个运算符重载函数

③:该对象在头文件 <iostream> 中声明,具有外部链接和静态存储期:它在程序的整个生命周期内存在,所以我们直接就能使用

❓️:cout<<会自动识别类型的本质是什么?

💡

①:类ostream中已经给你实现好了多种<<操作符的各种重载,所以对于不同的内置类型都可以进行识别和操作

②:而count是类ostream的对象,调用了类ostream中的函数!所以cout<< 等同于cout.operator<<(123);

对于双操作数的运算符的理解:

对于<<的认识:

需知:系统规定双操作数的运算符,第一个参数是左操作数,第二个参数是右操作数

所以:<<是一个双操作数的操作符,第一个参数为左操作数cout,第二个参数为右操作数变量


二:<<操作符的重载

上面类ostream中实现的多种对于<<操作符的重载,都是针对内置类型的,而我们自己实现的类,也想使用<<和>>,则需要自己手动实现一个针对类类型的<<操作符的重载。

但是实现过程会遇见多个问题,将这些问题逐一解决,则可以正确实现!

问题1:参数颠倒

类中的声明:

class Date { public: Date(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() const { printf("%d-%d-%d\n", _year, _month, _day); } void operator<<(ostream& out); private: int _year; int _month; int _day; };

类外的定义:

void Date::operator<<(ostream& out) { out << _year << "/" << _month << "/" << _day << endl; }

main函数中的使用:

发现main函数中无法使用?!

解释:

①:如需知所言,所以我们平时写的cout<<d1,cout就是<<的第一个参数,d1是<<的第二个参数,但是当我们像上面那样写,第一个参数是隐藏的this!所以和我们想要的相反(此时d1 << cout 是可以的)

②:所以我们要避免第一个参数被this占据,所以将<<操作符重载声明和定义都写在类外,也就是全局函数


问题2:无法访问私有成员变量

类外的声明:

void operator<<(ostream& out, const Date&d); //而第一个参数不加const是因为 其会改变 记住就行

类外的定义:

void operator<<(ostream& out, const Date& d) { out << d._year << "/" << d._month << "/" << d._day << endl; }

解释:此时在声明中就会报错,因为全局函数没有权限访问私有成员变量,所以我们还得在类中的声明处,给该函数加上友元关键字,让该函数可以访问私有成员变量


问题3:无法连续使用<<

如下:

class Date { public: friend void operator<<(ostream& out, const Date& d); // 友元的声明 //... private: int _year; int _month; int _day; };

新的问题:

无法 cout << d1 << d2,而真正的cout是可以连续的进行打印的,这是因为类ostream中实现的<<操作符的重载函数的返回值是ostream类型,所以当连续使用的时候,返回值作为下一次<<的参数,就实现了连续的打印,而我们的返回值是void,当然不能cout << d1 << d2啦~

连续插入 d1 和 d2 实际上就是两次函数的调用,这里先执行的是cout<<d1,

解决方案💡:

我们把返回值改为 ostream 就行,把 out这个对象返回回去。


问题4:最终版本

进行如下的改进:

类中的声明:

class Date { public: // ... friend ostream& operator<<(ostream& out, const Date& d); // 友元的声明 private: int _year; int _month; int _day; };

类外的定义:

#include "Date.h" ostream& operator<<(ostream& out, const Date& d) { out << d._year << "/" << d._month << "/" << d._day << endl; return out; }

main中使用:

int main(void) { Date d1(2022, 3, 20); Date d2(2021, 5, 1); cout << d1 << d2; return 0; }

此时在main函数可以连续的打印了


三:>>操作符的重载

>>和<<是同理的,只不过>>是istream的对象,所以代码如下:

类中的声明:

class Date { public: // ... friend ostream& operator<<(ostream& out, const Date& d); friend istream& operator>>(istream& in, Date& d); private: int _year; int _month; int _day; };

类外的的定义:

#include "Date.h" istream& operator>>(istream& in, Date& d) { in >> d._year >> d._month >> d._day; return in; }

main函数中的使用:

int main(void) { Date d1(2022, 3, 20); Date d2(2021, 5, 1); printf("请输入两个日期:\n"); cin >> d1 >> d2; printf("你输入的日期是:\n"); cout << d1 << d2; return 0; }

解释:和cout类似,cin是istream类的全局对象


四:细节补充

Q1:为什么上面实现的函数中,out和in参数都没有使用const修饰?

Q2:为什么上面实现的函数中,返回值都采取引用返回,可以采取值返回吗?

Q3:使用流提取符>>的重载函数中,为什么参数Date不用const修饰,起到保护作用?

Q4:为什么scanf要取地址?而cin不用?

A1:out和in就是cout和cin的引用,所以这个问题可以转化为,为什么不能对cout和cin使用const修饰,这是因为不管是cout打印还是cin读取,都会对cout或cin的对象产生改变,会修改流内部的缓冲区、状态位和格式标志,所以不能const修饰!

A2:首先采用引用返回是因为这个返回对象再函数栈帧销毁之后仍存在,所以可以起到避免拷贝的效果,其次也不能采取值返回,因为不管是ostream类还是istream类的拷贝构造都是被禁用的,禁用的原因不作过多解释

A3:因为>>会改变对象,是把用户输入的值赋值给对象的成员变量,所以Date会被改变,自然不能让Date被const修饰,而<<的参数Date因为不会被改变,所以可以const修饰

A4:因为scanf要改变变量,所以需要得到变量的地址;而cin不需要,因为C++有引用!


📌 [ 作者 ] shylyly
📃 [ 首次发布 ] 2025.3.1
❌ [ 最新修改 ] 2026.7.23
📜 [ 声明 ] 由于笔者水平有限,文中难免有疏漏或不妥之处,还望读者不吝赐教

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/24 20:46:43

河南精密机加工工厂|10 人 SolidWorks+UG 共享云主机完整配置方案

河南本地精密机加工企业以五金精密零部件、汽车结构件、工装夹具、模具加工为主&#xff0c;研发团队一般 8–10 人&#xff0c;同时使用 SolidWorks 做零件 / 工装建模、UG 做分型与多轴刀路编程。传统一人一台工作站投入高、新旧电脑性能参差不齐、图纸分散易流失、车间电磁干…

作者头像 李华
网站建设 2026/7/24 20:45:21

宇树 G1/H1 人形机器人动作捕捉与实时模仿系统

该系统本质上不是传统的“机器人自己规划路线”&#xff0c;而是一套&#xff1a; 人体动作采集 实时遥操作 动作重定向 全身平衡控制 示教数据训练 系统&#xff0c;它要解决的核心问题不是“机器人从哪里走到哪里”&#xff0c;而是&#xff1a; 人做出一个动作后&#x…

作者头像 李华
网站建设 2026/7/24 20:43:54

统计学,是“万金油”还是“就业难”?

每年毕业季&#xff0c;“统计学找工作难吗&#xff1f;”这个问题总会萦绕在许多统计学子心头。一方面&#xff0c;大数据、人工智能的浪潮似乎让数据相关专业炙手可热&#xff1b;另一方面&#xff0c;面对市场上琳琅满目的技术岗位要求&#xff0c;许多普通学生又感到迷茫和…

作者头像 李华
网站建设 2026/7/24 20:43:45

2026企业AI Agent落地指南:从0到1实现业务价值增长(小白程序员必看)

本文详细解析了企业级AI Agent的四大进化路径&#xff0c;揭示了多数企业仅停留在浅层应用的原因。文章深入剖析了AI投入无回报的三大落地死穴&#xff1a;盲目算力消耗、数据孤岛及传统流程不兼容&#xff0c;并提供了客服营销、标准化业务闭环等优选落地场景。同时&#xff0…

作者头像 李华
网站建设 2026/7/24 20:43:39

如何快速上手OpenRPA:企业级自动化完整指南

如何快速上手OpenRPA&#xff1a;企业级自动化完整指南 【免费下载链接】openrpa Free Open Source Enterprise Grade RPA 项目地址: https://gitcode.com/gh_mirrors/op/openrpa 你是否厌倦了每天重复的鼠标点击和键盘操作&#xff1f;是否渴望将宝贵时间从枯燥的重复任…

作者头像 李华