当前课程知识点:基于Linux的C++ >  第十讲 操作符重载 >  10.10 流操作符重载(一) >  LinuxCPP1010

返回《基于Linux的C++》慕课在线视频课程列表

LinuxCPP1010在线视频

LinuxCPP1010

下一节:LinuxCPP1011

返回《基于Linux的C++》慕课在线视频列表

LinuxCPP1010课程教案、知识点、字幕

下一节是流操作符的重载

流操作符这个重载过程有一点点复杂

我们首先来看流操作符重载的一般形式

正常情况下面

一个流的重载 流式操作的重载

必须使用这个固定的格式

friend ostream& operator<<( ostream&os,

constCouple& c);

friend istream& operator>>( istream& is,

Couple& c ) 固定的

必须按照这个模式来 为什么呢

因为我们流式操作的语义就是这样

为什么叫流式操作呢

你记得我们怎么写的吧 cout<

它是连写的 这是流操作最重要的一个本质

所以cout<

它做出来以后 它会把a输出出去

没错 但是这个结果做出来

它必须能够返回cout

然后才能<

连写模式就意味着这个流操作

它的格式是固定的

它必须返回输出流或输入流的一个引用

这是必须的

同时它的第一个参数

也必须是那个输出流和输入流的引用

我们实际上返回的就是它的第一个参数

所以要重载成友元 必须按照这个模式来

第二个参数才是你要输出的

或者要输入的那个对象

如果是输出 当然是constCouple&

如果是输入 当然是Couple&

这是我们流式操作符重载的最基本的方式

我们来看实现 实现其实不复杂

ostream& operator<<

我们要输出 向我们输出流里面输出 对吧

我们就os<< "( " <

" <

最后记得returnos 就完了

这是我们的标准流操作 就输出了

你重载了 以后直接就可以按照这个格式

就输出这个Couple对象本身

而不需要一个字段、一个字段去调用它

那好麻烦

所以你要重载了这个流操作符

那一步操作调用就完事了嘛 那多简单

输入操作符也一样

istream & operator>>(istream & is, Couple& c)

is>>c._a>>c._b

我们就按照这个格式输入

这两个字段就完了 return is

return is 返回它的输入流 完事

代码很简单 但是你要记住

我这两个实现 格式是不统一的

我输出的时候是按照

小括号对的格式输出的

我输入的时候 直接输入俩数的

中间是以空格键、Tab键、回车键分隔开的

不是小括号对、逗号那个格式把它成组化的

特别注意这一点

所以你刚才输出那个数据

不能拿过来输入的 格式是不匹配的

注意这个

用法呢 就我刚才讲了

你重载了这个流操作以后

这个用法本身是简单的

就是cin>>b,cout<

然后就完事了

这个就是流操作符重载的一般的方式

不一般的方式 我们后面接着讲

我们现在要补充一些

关于流与文件的知识

首先 我们要知道在C++库里边

实际上提供一个标准的流类库

它提供了丰富的功能 你可以使用

比如讲cin、cout

实际上就是在标准流类库里面提供的

全局的流对象 你可以拿过来用的

关于这个流 它有一些特定的格式的处理

包括如何设定整个流的输入输出格式

包括如何操纵这样的一个流

我们称之为操作符

包括如何和文件挂接在一起 形成文件流

同学们在使用这个流的时候

需要对这些知识有一些基本的了解

那么我们现在就对流与文件

做一个简单的介绍

我们首先来看标准流类库

我们一开始要知道的一个基本概念

就是什么叫流 流是什么东西

流是数据从源到目的地的一个移动

这个就叫流

所以它一定有两个方向 两个端口

一个是它的源 一个是它的目的

从哪到哪 这是很明确的一个地方

根据这个数据流动的性质

我们可以设定这个流到底是输入的流

还是输出的流

也就是数据是向流中插入的

还是从流中提取出来的

这是一个和输入输出不同的概念

待会我们再解释

在标准流类库里边

输入输出流使用iostream这个类

输入流使用istream这个类

输出流使用ostream这个类

这是三个类名

如果流数据本身是一个字符串

它就使用的是一个字符串流

所以输入输出字符串流就是strstream

如果是个输入字符串流呢

就是istrstream(i/o就表示input/output)

如果是一个输出的字符串流

就ostrstream 很明确吧 明确

相对应地 如果处理的是文件类的操作

那么它就有一个输入文件流

和输出文件流和一个输入输出文件流

所以相对应的文件名就是

ofstream、ifstream还有fstream

这是几种流类 你都可以用

在标准流类库里面定义了四个全局对象

这四个全局流对象你都可以直接用

一个是std::cout 一个是std::cin

还有两个是std::cerr、std::clog

对于cout来讲 它是一个标准输出流对象

一般对应于我们标准输出设备

主要就是我们的计算机屏幕了

cin是一个标准输入流对象

一般对应我们标准输入设备

主要是我们的键盘

cerr是标准错误流对象

clog是标准日志流对象

前者主要对应于标准错误输出设备

后者对应我们的标准日志输出设备

在这四个全局流对象中除了cin

是输入流的对象以外——cin是我们的

istream这个流类的一个对象

cout、cerr和clog

它们都是用于输出目的的

所以都是ostream类的对象

这是我们标准流类库提供的

四个全局流对象

它们是全局的 你可以直接用

在流式操作中最重要的两个操作

就是插入与提取 插入叫insert

它的目的是将数据和数据对象

插入到我们的流里边去

插入操作符有时候也称输出操作符

你比如说std::cout<<"Hello World!"

它就把“Hello World!”这个字符串

插入到这个流里面去

然后流的那个设备

就能够把这个信息就输出了

就这个意思 所以它叫一个插入符

提取呢 是从这个流中提取一个数据对象

那么这就意味着

我们事实上是要从流中获取数据的

所以有时候我们称它为输入操作符

你比如说 我定义一个整型变量a

然后cin>>a 那就完成输入整型变量值的

这样一个工作

所以它叫一个提取操作符

这个数据是从这个流中提取出来的

那个流对应我们的输入嘛 对吧

所以这个地方是提取过来的

所以这叫提取操作符

因为这个流的设计本身是非常复杂的

流可能会被重新定向或者被束定

束定的意思就是什么

我可以把一个输入流和一个输出流

给挂接在一起

它就形成两个流之间的一种束定的关系

把它们绑一块的那个意思

因为会出现这种情况 所以用这个术语

使用输入和输出这两个术语

有可能会让人迷惑

它到底是在输入 还到底是在输出

因为那往往涉及到这个数据

它从哪来 到哪去

有一个主观的基本点

有一个基准

我才能、才说输入输出嘛 对吧

而插入和提取呢

我仅以那个流——所操纵的那个流来为对象

到底是把那个数据朝流里放

还是从流中取出来

它这个情况 性质是不一样的

所以当我们说流式操作的时候

说插入符和提取符

插入操作或提取操作其实更准确

要比输入操作、输出操作更准确

常用的输入输出流的一些函数有:

你比如说eof

我们判定流是不是结束了

你比如说get

我们要从流中读取单个字符

你比如讲get

我从流中读取一个字符串

比如讲getline 读取整行文本

比如讲输出单个字符put

所有的这些操作

都是流式操作替我们提供的 你可以用

我们这里边只是举了几个例子

只是把这五个函数给它列给大家

实际上在流操作里面

所提供的函数远远不止这五个

很多函数你都可以用

想了解的同学

去看一下帮助手册就能够明白

很多函数的解释是非常直接的

流式操作的时候

为了控制这些量的输入和输出

它事实上是有一系列格式的标志

这些格式标志都定义在一个特殊的类

我们称它ios_base

这一个输入输出流的一个基类里面

相当靠上的一个类

它定义的这些格式的标志

它使用了一个匿名的枚举型

每一个都定义了指定的这样一个文字

这些文字的定义相当巧妙

基本上都是按位的格式来定义的

一位一个 一位一个 按照这个模式

为什么呢 因为C和C++支持我们的位操作

这样的话

按照位标志的模式来去处理的话

它处理的效率是非常高的

这就是流的格式标志

正常情况下 它应该是一个int型

但它实际上

是为了表明这个流格式的一个属性

专门定义了一个型 叫fmtflags

把一个整数型定义成了格式标志

就这个意思 就是fmtflags

用这个型来指代我们流的格式标志

当你使用的时候 就使用它 就行了

这些流的格式标志中

有一个非常重要的地方

就是它们的设计都是按位来做的

我刚才不讲了吗 对吧

正常情况下 是使用32位的整数

来保存我们的流格式信息

一个32位的整数

所以它事实上最多只能保持32个状态

想使用它 就是ios_base::fmtflags

每一个标志位都可以单独设置或清除

有一些特定的格式很特殊

几种格式是一种互相排斥的关系

那么这些格式彼此独立

但它们本身是互相排斥的

所以合在一起就形成

我们称之为“位组”的一个东西

它表示一个特定的标志位的集合

位组中的每一个标志位都是互相排斥的

所以像这样的一个位组设定的时候

基本上就是按照像这样的一个模式

要传上那个参数之后

传上它指定的位组

必须按照这个格式来

如果你不传位组信息

单参数版本是无效的

还有一些设定格式的时候

需要用户传递一些附加的信息

这个附加信息我们需要作为

用户的自定义参数传进去才行

这种模式是相当必要的

但是我要特别跟同学们强调一点

其实流操作对于一个简单量的输出

尤其是简单多个量的连续输出

它实际上非常非常方便的

用起来看上去也很神奇

它就能够工作 但实际上

对一个复杂数据的复杂格式输出

流式操作是极其不方便的

效率(注:指编程效率)实际上是非常低的

不如printf函数调用

输出一个复杂信息的时候

我建议同学们其实还是应该回到

printf这样的函数里面去输出

不要使用cout 只有简单量的输出

使用cout其实更方便一些

但cout确实有一个好处 就是什么呢

它支持重载 一旦我们重载了

这个流操作符 那么大对象的输出输入

它不就更方便了吗

对使用者来讲就方便了很多

基于Linux的C++课程列表:

第一讲 C/C++基本语法元素

-1.1 提纲

--LinuxCPP0101

-1.2 程序设计的基本概念

--LinuxCPP0102

-1.3 简单C/C++程序介绍

--LinuxCPP0103

-1.4 程序设计的基本流程

--LinuxCPP0104

-1.5 基本语法元素

--LinuxCPP0105

-1.6 程序设计风格

--LinuxCPP0106

-1.7 编程实践

--LinuxCPP0107

-第一讲 C/C++基本语法元素--编程实践提交入口

第二讲 程序控制结构

-2.1 提纲

--LinuxCPP0201

-2.2 结构化程序设计基础

--LinuxCPP0202

-2.3 布尔数据

--LinuxCPP0203

-2.4 分支结构

--LinuxCPP0204

-2.5 break语句

--LinuxCPP0205

-2.6 循环结构

--LinuxCPP0206

-2.7 编程实践

--LinuxCPP0207

-第二讲 程序控制结构--编程实践提交入口

第三讲 函数

-3.1 提纲

--LinuxCPP0301

-3.2 函数声明、调用与定义

--LinuxCPP0302

-3.3 函数调用栈框架

--LinuxCPP0303

-3.4 编程实践

--LinuxCPP0304

-第三讲 函数--编程实践提交入口

第四讲 算法

-4.1 提纲

--LinuxCPP0401

-4.2 算法概念与特征

--LinuxCPP0402

-4.3 算法描述

--LinuxCPP0403

-4.4 算法设计与实现

--LinuxCPP0404

-4.5 递归算法(一)

--LinuxCPP0405

-4.6 递归算法(二)

--LinuxCPP0406

-4.7 容错与计算复杂度

--LinuxCPP0407

-4.8 编程实践

--LinuxCPP0408

-第四讲 算法--编程实践提交入口

第五讲 程序组织与开发方法

-5.1 提纲

--LinuxCPP0501

-5.2 库与接口

--LinuxCPP0502

-5.3 随机数库(一)

--LinuxCPP0503

-5.4 随机数库(二)

--LinuxCPP0504

-5.5 作用域与生存期

--LinuxCPP0505

-5.6 典型软件开发流程(一)

--LinuxCPP0506

-5.7 典型软件开发流程(二)

--LinuxCPP0507

-5.8 编程实践

--LinuxCPP0508

-第五讲 程序组织与开发方法--编程实践提交入口

第六讲 复合数据类型

-6.1 提纲

--LinuxCPP0601

-6.2 字符

--LinuxCPP0602

-6.3 数组(一)

--LinuxCPP0603

-6.4 数组(二)

--LinuxCPP0604

-6.5 结构体

--LinuxCPP0605

-6.6 编程实践

--LinuxCPP0606

-第六讲 复合数据类型--编程实践提交入口

第七讲 指针与引用

-7.1 提纲

--LinuxCPP0701

-7.2 指针基本概念

--LinuxCPP0702

-7.3 指针与函数

--LinuxCPP0703

-7.4 指针与复合数据类型(一)

--LinuxCPP0704

-7.5 指针与复合数据类型(二)

--LinuxCPP0705

-7.6 字符串

--LinuxCPP0706

-7.7 动态存储管理(一)

--LinuxCPP0707

-7.8 动态存储管理(二)

--LinuxCPP0708

-7.9 引用

--LinuxCPP0709

-7.10 编程实践

--LinuxCPP0710

-第七讲 指针与引用--编程实践提交入口

第八讲 链表与程序抽象

-8.1 提纲

--LinuxCPP0801

-8.2 数据抽象(一)

--LinuxCPP0802

-8.3 数据抽象(二)

--LinuxCPP0803

-8.4 链表(一)

--LinuxCPP0804

-8.5 链表(二)

--LinuxCPP0805

-8.6 链表(三)

--LinuxCPP0806

-8.7 链表(四)

--LinuxCPP0807

-8.8 函数指针(一)

--LinuxCPP0808

-8.9 函数指针(二)

--LinuxCPP0809

-8.10 抽象链表(一)

--LinuxCPP0810

-8.11 抽象链表(二)

--LinuxCPP0811

-8.12 编程实践

--LinuxCPP0812

-第八讲 链表与程序抽象--编程实践提交入口

第九讲 类与对象

-9.1 提纲

--LinuxCPP0901

-9.2 程序抽象与面向对象

--LinuxCPP0902

-9.3 类类型

--LinuxCPP0903

-9.4 对象(一)

--LinuxCPP0904

-9.5 对象(二)

--LinuxCPP0905

-9.6 类与对象的成员(一)

--LinuxCPP0906

-9.7 类与对象的成员(二)

--LinuxCPP0907

-9.8 类与对象的成员(三)

--LinuxCPP0908

-9.9 继承(一)

--LinuxCPP0909

-9.10 继承(二)

--LinuxCPP0910

-9.11 继承(三)

--LinuxCPP0911

-9.12 多态(一)

--LinuxCPP0912

-9.13 多态(二)

--LinuxCPP0913

-9.14 编程实践

--LinuxCPP0914

-第九讲 类与对象--编程实践提交入口

第十讲 操作符重载

-10.1 提纲

--LinuxCPP1001

-10.2 四则运算符重载(一)

--LinuxCPP1002

-10.3 四则运算符重载(二)

--LinuxCPP1003

-10.4 关系与下标操作符重载

--LinuxCPP1004

-10.5 赋值操作符重载(一)

--LinuxCPP1005

-10.6 赋值操作符重载(二)

--LinuxCPP1006

-10.7 赋值操作符重载(三)

--LinuxCPP1007

-10.8 赋值操作符重载(四)

--LinuxCPP1008

-10.9 赋值操作符重载(五)

--LinuxCPP1009

-10.10 流操作符重载(一)

--LinuxCPP1010

-10.11 流操作符重载(二)

--LinuxCPP1011

-10.12 流操作符重载(三)

--LinuxCPP1012

-10.13 操作符重载总结

--LinuxCPP1013

-10.14 编程实践

--LinuxCPP1014

-第十讲 操作符重载--编程实践提交入口

第十一讲 泛型编程

-11.1 提纲

--LinuxCPP1101

-11.2 泛型编程概览

--LinuxCPP1102

-11.3 异常处理机制(一)

--LinuxCPP1103

-11.4 异常处理机制(二)

--LinuxCPP1104

-11.5 运行期型式信息(一)

--LinuxCPP1105

-11.6 运行期型式信息(二)

--LinuxCPP1106

-11.7 模板与型式参数化

--LinuxCPP1107

-11.8 题外话:术语翻译

--LinuxCPP1108

-11.9 泛型编程实践(一)

--LinuxCPP1109

-11.10 泛型编程实践(二)

--LinuxCPP1110

-11.11 泛型编程实践(三)

--LinuxCPP1111

-11.12 泛型编程实践(四)

--LinuxCPP1112

-11.13 泛型编程实践(五)

--LinuxCPP1113

-11.14 泛型编程实践(六)

--LinuxCPP1114

-11.15 泛型编程实践(七)

--LinuxCPP1115

-11.16 泛型编程实践(八)

--LinuxCPP1116

-11.17 泛型编程实践(九)

--LinuxCPP1117

-11.18 泛型编程实践(十)

--LinuxCPP1118

-11.19 编程实践

--LinuxCPP1119

-第十一讲 泛型编程--编程实践提交入口

第十二讲 Linux系统编程基础

-12.1 提纲

--LinuxCPP1201

-12.2 程序执行环境(一)

--LinuxCPP1202

-12.3 程序执行环境(二)

--LinuxCPP1203

-12.4 程序执行环境(三)

--LinuxCPP1204

-12.5 程序执行环境(四)

--LinuxCPP1205

-12.6 输入输出(一)

--LinuxCPP1206

-12.7 输入输出(二)

--LinuxCPP1207

-12.8 文件系统

--LinuxCPP1208

-12.9 设备

--LinuxCPP1209

-12.10 库(一)

--LinuxCPP1210

-12.11 库(二)

--LinuxCPP1211

-12.12 makefile文件(一)

--LinuxCPP1212

-12.13 makefile文件(二)

--LinuxCPP1213

-12.14 makefile文件(三)

--LinuxCPP1214

-12.15 编程实践

--LinuxCPP1215

-第十二讲 Linux系统编程基础--编程实践提交入口

第十三讲 进程编程

-13.01 提纲

--LinuxCPP1301

-13.02 进程基本概念

--LinuxCPP1302

-13.03 信号

--LinuxCPP1303

-13.04 进程管理(一)

--LinuxCPP1304

-13.05 进程管理(二)

--LinuxCPP1305

-13.06 进程管理(三)

--LinuxCPP1306

-13.07 进程间通信(一)

--LinuxCPP1307

-13.08 进程间通信(二)

--LinuxCPP1308

-13.09 进程间通信(三)

--LinuxCPP1309

-13.10 进程间通信(四)

--LinuxCPP1310

-13.11 进程池

--LinuxCPP1311

-13.12 编程实践

--LinuxCPP1312

-第十三讲 进程编程--编程实践提交入口

第十四讲 线程编程

-14.1 提纲

--LinuxCPP1401

-14.2 线程基本概念

--LinuxCPP1402

-14.3 线程管理(一)

--LinuxCPP1403

-14.4 线程管理(二)

--LinuxCPP1404

-14.5 线程管理(三)

--LinuxCPP1405

-14.6 线程管理(四)

--LinuxCPP1406

-14.7 线程同步机制(一)

--LinuxCPP1407

-14.8 线程同步机制(二)

--LinuxCPP1408

-14.9 C++11线程库(一)

--LinuxCPP1409

-14.10 C++11线程库(二)

--LinuxCPP1410

-14.11 C++11线程库(三)

--LinuxCPP1411

-14.12 C++11线程库(四)

--LinuxCPP1412

-14.13 C++11线程库(五)

--LinuxCPP1413

-14.14 编程实践

--LinuxCPP1414

-第十四讲 线程编程--编程实践提交入口

第十五讲 网络编程

-15.1 提纲

--LinuxCPP1501

-15.2 Internet网络协议

--LinuxCPP1502

-15.3 套接字(一)

--LinuxCPP1503

-15.4 套接字(二)

--LinuxCPP1504

-15.5 编程实践

--LinuxCPP1505

-第十五讲 网络编程--编程实践提交入口

课程文档

-课程PDF文件

LinuxCPP1010笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。