目录

一、为什么需要重载为全局函数

成员函数重载的问题

全局函数的优势

二、实现细节

1、输出运算符<<的重载

关键部分详解

1. 类定义部分

2. 运算符重载实现

3. main函数中的使用

为什么这样设计?

执行流程

输出结果

2、输入运算符>>的重载

关键部分详解

1. 类定义部分

2. 运算符重载实现

3. main函数中的使用

为什么这样设计?

执行流程

注意事项

示例输入输出

3、为什么需要友元(后面会详细讲解友元)

三、总结


        在C++中,重载输入(>>)和输出(<<)运算符时,通常需要将它们重载为全局函数而非成员函数,这与大多数其他运算符的重载方式不同。

一、为什么需要重载为全局函数

成员函数重载的问题

当我们将<<>>重载为类的成员函数时,函数实际上是这样的:

// 假设重载为成员函数
class MyClass {
public:ostream& operator<<(ostream& os);  // 成员函数版本
};

调用时的情况:

MyClass obj;
obj << cout;  // 这与常规用法相反!

问题在于:

  1. this指针作为隐式第一个参数,占据了左侧运算对象的位置

  2. 导致使用方式变为对象 << 流,这与常规的流 << 对象用法相反

  3. 破坏了代码的可读性和直观性

全局函数的优势

重载为全局函数可以解决这个问题:

ostream& operator<<(ostream& os, const MyClass& obj);

这样:

  1. 全局函数没有this指针!!!所以就没有上面的成员函数重载问题!!!

  2. 第一个参数是ostream对象(如cout

  3. 第二个参数是要输出的类对象

  4. 使用方式变为cout << obj,符合常规习惯


二、实现细节

1、输出运算符<<的重载

#include <iostream>
using namespace std;class MyClass {int data;
public:MyClass(int d) : data(d) {}friend ostream& operator<<(ostream& os, const MyClass& obj); // 声明为友元
};// 全局函数实现
ostream& operator<<(ostream& os, const MyClass& obj) {os << "MyClass data: " << obj.data;return os;
}int main() {MyClass obj(42);cout << obj << endl;  // 正常使用方式return 0;
}

要点:

  1. 返回ostream&以支持链式调用(如cout << a << b

  2. 第一个参数是输出流,第二个参数是要输出的对象

  3. 通常需要声明为类的友元以访问私有成员

关键部分详解

1. 类定义部分
  • int data:私有成员变量,存储类的数据

  • MyClass(int d):构造函数,初始化data成员

  • friend声明:将重载的<<运算符函数声明为友元,使其能访问私有成员data

2. 运算符重载实现
  • 返回类型:ostream&(输出流引用),支持链式调用

  • 第一个参数:ostream& os(输出流对象,如cout

  • 第二个参数:const MyClass& obj(要输出的对象,常量引用避免拷贝)

  • 函数体:

    • 使用os输出自定义格式的字符串和对象数据

    • 返回流对象os以支持链式操作

3. main函数中的使用
  • 创建MyClass对象obj,初始化data为42

  • cout << obj:调用我们重载的<<运算符,相当于operator<<(cout, obj)

  • << endl:继续使用返回的流对象进行链式操作

为什么这样设计?

  1. 全局函数而非成员函数

    • 如果是成员函数,调用方式会是obj << cout,不符合习惯

    • 全局函数可以保持cout << obj的自然语法

  2. 友元声明

    • 因为data是私有成员,普通全局函数无法访问

    • 声明为友元后,运算符函数可以访问私有成员

  3. 返回流引用

    • 使表达式可以连续使用,如cout << obj1 << obj2

    • 每次调用都返回流对象,供下一次操作使用

  4. const引用参数

    • 避免对象拷贝,提高效率

    • const保证不会意外修改对象状态

执行流程

  1. MyClass obj(42):创建对象,data初始化为42

  2. cout << obj

    • 编译器查找匹配的<<运算符

    • 找到我们重载的全局函数

    • 调用operator<<(cout, obj)

  3. 在运算符函数内:

    • cout输出字符串"MyClass data: "

    • 接着输出obj.data的值42

    • 返回cout引用

  4. << endl:对返回的cout执行换行操作

输出结果

程序运行后将输出:

        这种实现方式既保持了C++流操作的自然语法,又提供了对类对象输出的完全控制,是C++中实现自定义类型输出的标准做法。

2、输入运算符>>的重载

#include <iostream>
using namespace std;class MyClass {int data;
public:MyClass() : data(0) {}friend istream& operator>>(istream& is, MyClass& obj); // 声明为友元friend ostream& operator<<(ostream& os, const MyClass& obj); // 声明为友元
};// 全局函数实现
istream& operator>>(istream& is, MyClass& obj) {is >> obj.data;return is;
}// 全局函数实现
ostream& operator<<(ostream& os, const MyClass& obj) {os << "MyClass data: " << obj.data;return os;
}int main() {MyClass obj;cin >> obj;  // 从标准输入读取数据到objcout << obj << endl;return 0;
}

要点:

  1. 返回istream&以支持链式调用

  2. 第二个参数是非常量引用,因为要修改对象状态

  3. 通常需要处理可能的输入错误

关键部分详解

1. 类定义部分
  • int data:私有成员变量,存储类的数据

  • MyClass():默认构造函数,将data初始化为0

  • friend声明:将重载的>>运算符函数声明为友元,使其能访问私有成员data

2. 运算符重载实现
  • 返回类型:istream&(输入流引用),支持链式调用

  • 第一个参数:istream& is(输入流对象,如cin

  • 第二个参数:MyClass& obj(要输入的对象,非常量引用以便修改)

  • 函数体:

    • 使用is从输入流读取数据到obj.data

    • 返回流对象is以支持链式操作

3. main函数中的使用
  • 创建MyClass对象objdata初始化为0

  • cin >> obj:调用我们重载的>>运算符

    • 相当于operator>>(cin, obj)

  • 之后可以输出obj查看输入结果

为什么这样设计?

  1. 全局函数而非成员函数

    • 如果是成员函数,调用方式会是obj >> cin,不符合习惯

    • 全局函数可以保持cin >> obj的自然语法

  2. 友元声明

    • 因为data是私有成员,普通全局函数无法访问

    • 声明为友元后,运算符函数可以修改私有成员

  3. 返回流引用

    • 使表达式可以连续使用,如cin >> obj1 >> obj2

    • 每次调用都返回流对象,供下一次操作使用

  4. 非常量引用参数

    • 需要修改对象状态(将输入值赋给obj.data

    • 引用避免对象拷贝,提高效率

执行流程

  1. MyClass obj:创建对象,data初始化为0

  2. cin >> obj

    • 编译器查找匹配的>>运算符

    • 找到我们重载的全局函数

    • 调用operator>>(cin, obj)

  3. 在运算符函数内:

    • cin读取一个整数到obj.data

    • 返回cin引用

  4. 之后可以输出obj查看结果

注意事项

  1. 输入验证

    • 实际应用中应该添加输入验证

    • 例如检查输入是否成功:

      if(!(is >> obj.data)) {// 处理输入失败的情况
      }
  2. 链式调用:由于返回流引用,可以连续使用:

    MyClass a, b;
    cin >> a >> b;  // 连续输入两个对象
  3. 与输出运算符配合

    • 通常同时重载<<>>运算符

    • 这样对象既能输入也能输出

示例输入输出

假设用户输入:42

程序将把42存入obj.data,如果实现了<<重载,输出可能是:

        这种实现方式保持了C++流操作的自然语法,提供了对类对象输入的完全控制,是C++中实现自定义类型输入的标准做法。

3、为什么需要友元(后面会详细讲解友元)

        由于这些运算符需要访问类的私有成员,但又不能作为成员函数实现,因此通常需要将它们声明为类的友元函数。


三、总结

  1. 必须重载为全局函数:为了保持流 << 对象流 >> 对象的自然语法

  2. this指针问题:成员函数的隐式this参数会破坏运算符的常规使用顺序

  3. 友元声明:通常需要访问私有成员,因此要在类内声明为友元

  4. 返回流引用:支持链式操作

这种设计既保持了C++流操作的自然语法,又提供了足够的灵活性来定制类的输入输出行为。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ENS-317 Modbus TCP / 通用模式网关

在工业自动化的复杂网络中&#xff0c;以太网设备与串口设备的 “语言不通” 常常成为数据流转的阻碍。上海泗博自动化推出的 ENS-317 Modbus TCP / 通用模式网关&#xff0c;以强大的协议转换能力、灵活的配置方式和工业级可靠性&#xff0c;为设备互联提供一站式解决方案&…

AcWing 6478. 谁进线下了?III

原题链接 6478. 谁进线下了&#xff1f;III - AcWing题库 这是一道睿抗&#xff08;省赛&#xff09;题 一开始睿抗是啥都不知道 然后一看是省赛吓得我不轻 但读完题简简单单 一道很水的模拟题&#xff08;谁能解释一下睿抗啥意思&#xff09; 一起开康康 题目 Xepa Le…

openpnp - 不连接设备,只大概测试一下摄像头是否好使

文章目录openpnp - 不连接设备&#xff0c;只大概测试一下摄像头是否好使概述笔记备注备注ENDopenpnp - 不连接设备&#xff0c;只大概测试一下摄像头是否好使 概述 顶部相机摄像头在拆装过程中&#xff0c;可能被手上的静电打坏了。 现在和电脑连接是正常的&#xff0c;但是…

使用Python提取PDF大纲(书签)完整指南

&#x1f50d; 一、PDF大纲简介&#x1f4cc; ​PDF大纲&#xff08;Outline&#xff09;​​ 是PDF文档中的导航结构&#xff0c;通常显示在阅读器的侧边栏中&#xff0c;方便用户快速跳转到文档的不同部分。大纲通常以层级结构组织&#xff0c;包含标题和对应的页面位置。本文…

第39周——训练自己的数据集

目录 1. 下载数据 2. 配置开发环境 3. 预处理数据 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 1. 下载数据 百度网盘&#xff1a;百度网盘 请输入提取码 压缩文件中有两个文件夹&#xff0c;分别是Annot…

CentOS7中Docker的安装与卸载

CentOS7 从零开始:Docker 安装与卸载全指南(新手友好版) 作为一名刚接触 Linux 和容器技术的新手,你是否曾在安装 Docker 时被各种命令和报错搞得一头雾水?比如执行 yum install docker 时提示 “仓库不存在”,或者启动 Docker 后用 docker version 只显示 client 不显示…

解决MinIO上传图片后返回URL无法访问的问题

一、问题现象 上传接口返回了文件的访问路径&#xff0c;比如&#xff1a; http://127.0.0.1:9005/lease/20250808/xxx-uuid.png但是用浏览器直接打开该地址却显示权限拒绝,前端也访问不到:二、问题原因分析 桶权限设置不正确: MinIO默认桶权限是私有的&#xff0c;即使浏览器能…

系统网络端口安全扫描脚本及详解

#!/bin/bash # 系统服务端口安全扫描 - 修正版echo " 系统服务端口安全扫描报告 "# 1. 高风险端口识别 echo "⚠️ 对外开放的高风险端口:" awk /0.0.0.0:21/ {print " 端口 21 - FTP (明文传输)\n &#x1f6a8; 严重安全风险&#xff0c;建议…

DAY 39 图像数据与显存

知识点回顾 图像数据的格式&#xff1a;灰度和彩色数据模型的定义显存占用的4种地方 模型参数梯度参数优化器参数数据批量所占显存神经元输出中间状态 batchisize和训练的关系 一、 图像数据的介绍 1.1 灰度图像 从这里开始我们进入到了图像数据相关的部分&#xff0c;也是默认…

从大数据视角理解时序数据库选型:为何选择 Apache IoTDB?

目录一、什么是时序数据库&#xff1f;为什么你需要它&#xff1f;&#x1f527;典型应用场景&#xff1a;二、时序数据库选型维度有哪些&#xff1f;三、为什么推荐 Apache IoTDB&#xff1f;&#x1f9e0; Apache 顶级项目&#xff0c;工业 IoT 场景原生支持&#x1f680; 性…

[ MySQL 数据库 ] 环境安装配置和使用

目录 一. 数据库(DataBase) 1.定义: 2. 常见的数据库产品&#xff1a; 3. MySQL数据库 (1). 介绍 : (2). cmd命令行方式连接 MySQL (3). MySQL的常用命令 二. MySQL数据库 环境安装及配置 三. SQL 1.定义 : 2. DDL (1)数据库 (2)数据表 1. 字段(列)和记录(行) 2. 表特征 3.…

Numpy科学计算与数据分析:Numpy布尔索引与花式索引实战

Numpy高级索引 学习目标 通过本课程&#xff0c;学员将掌握Numpy中布尔索引和花式索引的使用方法&#xff0c;能够灵活运用这些高级索引技术进行复杂的数据操作和处理。 相关知识点 Numpy高级索引 学习内容 1 Numpy高级索引 1.1 布尔索引 布尔索引是Numpy中一种非常强大…

【Linux】patch补丁的生成与使用方法总结

引言 在 Linux 和开源世界中&#xff0c;patch 是一个极其强大且常用的工具。它允许开发者和系统管理员以增量方式修改文件&#xff0c;特别适用于源代码的更新、错误修复、功能补丁的分发与应用。 目录 引言 一、patch介绍 二、生成补丁文件 三、补丁文件内容解析 四、p…

杂谈 001 · VScode / Copilot 25.08 更新

原文链接https://www.castamerego.com/blog/talk-001 2025.08.08 , VS code 发布八月更新&#xff0c;同一天 Copilot 也更新了 GPT-5, 浅体验一下 VS code 更新 发行说明更新页面内跳转显示 AI 比例页面内跳转 Copilot 更新 对话回溯 checkpoints页面内跳转进度列表页面内…

微软发布Project Ire项目:可自主检测恶意软件的人工智能系统

微软Project Ire项目利用AI自主逆向工程并分类软件性质微软近日公布了Project Ire项目&#xff0c;这是一个能够自主进行逆向工程并分类软件性质的人工智能&#xff08;AI&#xff09;系统。该系统由大型语言模型&#xff08;LLM&#xff09;驱动&#xff0c;通过使用反编译器等…

k8s核心组件——kubelet详解

&#x1f680;Kubernetes 核心组件解析&#xff1a;什么是 Kubelet&#xff1f;它的作用是什么&#xff1f; 在 Kubernetes&#xff08;K8s&#xff09;集群中&#xff0c;Kubelet 是最重要的 Node 组件之一&#xff0c;它负责管理和维护 Pod 的生命周期&#xff0c;确保容器在…

C++ 部署LSTM(.onnx)

0、 背景 在工业自动化控制领域&#xff0c;预测某些变量是否关键。根据工厂的数据&#xff0c;训练好模型之后&#xff0c;将其转我通用的onnx 模型&#xff0c;并实现高效的推理。 模型训练 import numpy as np from para import * from data_utils import MyDataset from da…

深度学习-卷积神经网络CNN-1×1卷积层

1x1卷积核&#xff0c;又称为网中网&#xff08;Network in Network&#xff09;&#xff1a;NIN卷积的本质是有效提取相邻像素间的相关特征&#xff0c;而11的卷积显然没有此作用。它失去了卷积层的特有能力——在高度和宽度维度上&#xff0c;识别相邻元素间相互作用的能力。…

使用 Python 异步爬虫抓取豆瓣电影Top250排行榜

导读 在现代网络爬虫开发中,面对 海量网页数据、慢速响应的网络接口,传统的同步爬虫方式已经不能满足高效抓取需求。本文将手把手带你构建一个 基于 aiohttp + asyncio 的异步爬虫系统,实战目标是抓取豆瓣电影 Top250 排行榜中的电影名称、评分和详情页地址。 目录 导读 …

云原生开发全面解析:从核心理念到实践挑战与解决方案

1. 云原生开发的核心理念与定义 云原生&#xff08;Cloud Native&#xff09;是一种基于云计算环境设计和运行应用程序的方法论&#xff0c;其三大技术支柱为容器化、微服务和声明式API。根据CNCF定义&#xff0c;云原生技术通过标准化接口和自动化管理&#xff0c;使应用具备…