微信公众号:「小林coding」

用简洁的方式,分享编程小知识。

01 流插入<<运算符的重载

C++ 在输出内容时,最常用的方式:

std::cout << 1 <<"hello";

问题:

  • 那这条语句为什么能成立呢?
  • cout 是什么?"<<" 运算符能用在 cout 上呢?

原因:

  • 实际上,cout 是在 iostream 头文件中定义的 ostream 类的对象。
  • "<<" 能够用在 cout 上是因为,在 ostream 类对 "<<" 进行了重载

对于std::cout << 1 <<"hello";这条语句,有可能按以下的方式重载成 ostream 类的成员函数:

ostream & ostream::operator<<(int n)
{
.... // 输出n整型的代码
return *this;
} ostream & ostream::operator<<(const char * s)
{
.... // 输出s字符串的代码
return *this;
}
  • std::cout << 1;语句,等价于cout.operator<<(1);
  • std::cout << "hello";语句,等价于cout.operator<<("hello");
  • std::cout << 1 <<"hello";语句,等价于( cout.operator<<(1) ).operator<<("hello");

02 流插入<<运算符重载的例子

假定我们要想把某个对象里的内容进行打印输出,那么我们可以重载 ostream 类的流插入 << 运算符。

下面以 CStudent 类作为例子:

class CStudent // 学生类
{
public:
// 构造函数
CStudent(int id = 0, int age = 0, string name = ""):m_id(id), m_age(age), m_name(name) { } // 将该函数声明成友元函数
// 目的是使得函数可以访问CStudent类的私有成员变量
friend ostream & operator<<(ostream & o, const CStudent & s); private:
int m_age; // 年龄
int m_id; // ID号
string m_name; // 名字
}; // 重载ostream对象的流插入<<运算符函数
// 目的是使得能打印输出CStudent对象的信息
ostream & operator<<(ostream & o, const CStudent & s)
{
o << s.m_id << "," << s.m_age << "," << s.m_name;
return o;
} int main()
{
CStudent stu(1, 20, "小林coding");
std::cout << stu ; // 输出std对象的全部信息 return 0;
}

输出结果:

1,20,小林coding

需要注意是 ostream & operator<<(ostream & o, const CStudent & s) 函数是全局的,所以函数的第一个参数必须要传入 ostream 的对象,并且 CStudent 类需要将此函数声明成友元函数,使得函数可以访问 CStudent 类的私有成员变量。

03 流提取>>运算符重载的例子

还是以 CStudent 类作为例子,假设想通过键盘的输入的内容,来初始化对象,则我们可以重载 istream 类的流提取 >> 运算符。

class CStudent // 学生类
{
public: // 构造函数
CStudent(int id = 0, int age = 0, string name = ""):m_id(id), m_age(age), m_name(name) { } // 将该函数声明成友元函数
// 目的是使得函数可以访问CStudent类的私有成员变量
friend ostream & operator<<(ostream & o, const CStudent & s); // 将该函数声明成友元函数
// 目的是使得函数可以给CStudent类的私有成员变量进行赋值
friend istream & operator>>(istream & is, CStudent & s); private:
int m_age; // 年龄
int m_id; // ID号
string m_name; // 名字
}; // 重载ostream对象的流插入<<运算符函数
// 目的是使得能打印输出CStudent对象的信息
ostream & operator<<(ostream & o, const CStudent & s)
{
o << s.m_id << "," << s.m_age << "," << s.m_name;
return o;
} // 重载istream对象的流提取>>运算符函数
// 目的是使得初始化CStudent对象的内容
istream & operator>>(istream & is, CStudent & stu)
{
string inputStr;
is >> inputStr; int pos = inputStr.find(",", 0); // 查找首次出现逗号的位置
string tmpStr = inputStr.substr(0, pos); // 截取从0到pos位置的字符串
stu.id = atoi(tmpStr.c_str()); // atoi可以将char*类型的内容转成int类型 int pos2 = inputStr.find(",", pos + 1); // 查找第二次出现逗号的位置
tmpStr = inputStr.substr(pos + 1, pos2 - pos -1); // 取出age的值
stu.age = atoi(tmpStr.c_str()); // atoi可以将char*类型的内容转成int类型 tmpStr = inputStr.substr(pos2 + 1, inputStr.length() - pos2 - 1); // 取出name的值
stu.name = tmpStr; return is;
} int main()
{
CStudent stu; // 将输入的信息,初始化stu对象
cin << stu; // 输出std对象的信息
cout >> stu; return 0;
}

输入内容和输出内容:

// 输入内容:
1,20,小林coding // 输出内容:
1,20,小林coding

04 小结

要想流插入 << 运算符和流提取 >> 运算符能针对自定义的对象,那么我们就需要重载针对该对象的 ostream 类的 << 运算符 和 istream>> 运算符,并且只能重载成全局的函数,然后在 CStudent 类里需要把上面的两个重载函数声明成友元函数,使得两个重载的函数可以访问和赋值 CStudent 类里的私有成员函数。


C++ 流插入"<<"和流提取">>"运算符的重载的更多相关文章

  1. C++重载流插入和流输出运算符

    demo: /* Name: 重载输入输出流运算符使力代码 Copyright: qianshou Author: zhaozhe Date: 07/12/13 00:11 Description: ...

  2. C++对运算符进行重载学习笔记

    1.  一个类的成员函数是暗含着 this 指针的,eg; #include<iostream> using namespace std; class A{ public: A(){ x ...

  3. C++重载流插入运算符和流提取运算符【转】

    C++的流插入运算符“<<”和流提取运算符“>>”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream.cin和cout分别是 ...

  4. c++ 控制台流和字符串流

    前言 上一章节简单介绍c++中关于流的概念,这两章节将重点讲解如何使用,本章讲解控制台流和字符串流. 控制台输出流 输出流定义在头文件中,使用输出流最简单的方法就是 使用<<运算符.通过你 ...

  5. 流类库继承体系(IO流,文件流,串流)和 字符串流的基本操作

    一.IO.流 数据的输入和输出(input/output简写为I/O) 对标准输入设备和标准输出设备的输入输出简称为标准I/O 对在外存磁盘上文件的输入输出简称为文件I/O 对内存中指定的字符串存储空 ...

  6. java 21 - 12 IO流的打印流

    打印流 字节流打印流 PrintStream 字符打印流 PrintWriter打印流的特点: A:只有写数据的,没有读取数据.只能操作目的地,不能操作数据源.(只能写入数据到文件中,而不能从文件中提 ...

  7. Java I/O第二篇 之 (缓冲流 随机流 数组流 数据流)

    1:缓冲流 BufferedReader  BufferedWriter 具有较强的读写能力,能单独读写一行数据,能够减少对硬盘的访问次数. /** * 缓冲流 能够增强对问价数据的可读性,减少访问读 ...

  8. RecyclerView实例-实现可下拉刷新上拉加载更多并可切换线性流和瀑布流模式(1)

    摘要 最近项目有个列表页需要实现线性列表和瀑布流展示的切换,首先我想到的就是上 [RecyclerView],他本身已经很好的提供了三种布局方式,只是简单做个切换应该是很简单的事情,如果要用Recyc ...

  9. IO流与NIO流

    JAVA IO流最详解   (转自CSDN) IO流上:概述.字符流.缓冲区(java基础)   一.IO流概述 概述: IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数 ...

随机推荐

  1. QAnet Encoder

    #!/usr/bin/python3# -*- coding: utf-8 -*-'''date: 2019/8/19mail: cally.maxiong@gmail.comblog: http:/ ...

  2. 在线程中显示一个窗口(多个UI线程)

    多数耗时操作可以异步执行,推荐async/await. 但和UI相关的部分仅能在UI线程执行,这时UI线程的耗时操作,导致界面卡死,不够友好. 我们可以创建一个单独的UI线程显示一个正在加载的窗口,可 ...

  3. jvm虚拟机笔记<二> 垃圾回收与内存分配

    确定对象已废弃需要两步: 利用可达性分析算法(与GC roots有关联——虚拟机栈中的对象,方法区静态对象,方法区常量对象,本地方法引用的对象)判断是否需要回收. 是否覆盖过finalize方法并执行 ...

  4. JAVA学习第二步,初级知识框架梳理

    回顾往期的学习,才发现已经学习了这么多知识点.这里复制了其他创作者的一些梳理结合自己的梳理.总结了自己在Java学习入门阶段的知识点.笔记自己了也写了详细的两本 第一章 Java面向对象 1-1包的定 ...

  5. 松软科技带你学前端:JavaScript 输出

    JavaScript 不提供任何内建的打印或显示函数. JavaScript 显示方案 JavaScript 能够以不同方式“显示”数据: 使用 window.alert() 写入警告框 使用 doc ...

  6. MySQL常见的8种SQL错误用法

    MySQL常见的8种SQL错误用法 前言 MySQL在2016年仍然保持强劲的数据库流行度增长趋势.越来越多的客户将自己的应用建立在MySQL数据库之上,甚至是从Oracle迁移到MySQL上来.但也 ...

  7. 《Linux/UNIX系统编程手册》第56章 SOCKET:介绍

    关键词: 1. socket基础 一个典型的客户端/服务器场景中,应用程序使用socket进行通信的方式如下: 各个应用程序创建一个socket.socket是一个允许通信的设备,两个应用程序都需要用 ...

  8. 如何在mysql数据库生成百万条数据来测试页面加载速度

    1.首先复制一条sql 在复制前,需要确定该记录是否有主键 若无,则代码非常简单, "; 复制的表名↑                                   粘贴的表名↑    ...

  9. 手工挖掘web常见漏洞时的一些经验总结

    一.前提: 漏洞挖掘原则 所有变量 所有头 cookie中的变量 逐个变量删除 漏洞的本质 数据与指令的混淆 对用户输入信息过滤不严判断失误,误将数据当指令 二.经典漏洞: 1.身份认证 常用弱口令/ ...

  10. springmvc的文件上传和JWT图形验证码

    相关pom依赖 <dependency> <groupId>commons-fileupload</groupId> <artifactId>commo ...