下一节是流操作符的重载
流操作符这个重载过程有一点点复杂
我们首先来看流操作符重载的一般形式
正常情况下面
一个流的重载 流式操作的重载
必须使用这个固定的格式
friend ostream& operator<<( ostream&os,
constCouple& c);
friend istream& operator>>( istream& is,
Couple& c ) 固定的
必须按照这个模式来 为什么呢
因为我们流式操作的语义就是这样
为什么叫流式操作呢
你记得我们怎么写的吧 cout<<a<<b<<c
它是连写的 这是流操作最重要的一个本质
所以cout<<a的结果
它做出来以后 它会把a输出出去
没错 但是这个结果做出来
它必须能够返回cout
然后才能<<b 对不对
连写模式就意味着这个流操作
它的格式是固定的
它必须返回输出流或输入流的一个引用
这是必须的
同时它的第一个参数
也必须是那个输出流和输入流的引用
我们实际上返回的就是它的第一个参数
所以要重载成友元 必须按照这个模式来
第二个参数才是你要输出的
或者要输入的那个对象
如果是输出 当然是constCouple&
如果是输入 当然是Couple&
这是我们流式操作符重载的最基本的方式
我们来看实现 实现其实不复杂
ostream& operator<<
我们要输出 向我们输出流里面输出 对吧
我们就os<< "( " <<c._a<< ",
" <<c._b<< " )" <<endl
最后记得returnos 就完了
这是我们的标准流操作 就输出了
你重载了 以后直接就可以按照这个格式
就输出这个Couple对象本身
而不需要一个字段、一个字段去调用它
那好麻烦
所以你要重载了这个流操作符
那一步操作调用就完事了嘛 那多简单
输入操作符也一样
istream & operator>>(istream & is, Couple& c)
is>>c._a>>c._b
我们就按照这个格式输入
这两个字段就完了 return is
return is 返回它的输入流 完事
代码很简单 但是你要记住
我这两个实现 格式是不统一的
我输出的时候是按照
小括号对的格式输出的
我输入的时候 直接输入俩数的
中间是以空格键、Tab键、回车键分隔开的
不是小括号对、逗号那个格式把它成组化的
特别注意这一点
所以你刚才输出那个数据
不能拿过来输入的 格式是不匹配的
注意这个
用法呢 就我刚才讲了
你重载了这个流操作以后
这个用法本身是简单的
就是cin>>b，cout<<a
然后就完事了
这个就是流操作符重载的一般的方式
不一般的方式 我们后面接着讲
我们现在要补充一些
关于流与文件的知识
首先 我们要知道在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确实有一个好处 就是什么呢
它支持重载 一旦我们重载了
这个流操作符 那么大对象的输出输入
它不就更方便了吗
对使用者来讲就方便了很多