解读C++重载ostream与istream

C++中,我们可以重载输入输出流操作符<<与>>来自定义其输入输出功能。

class Foo
{
public:
    Foo() :high(0), wide(0){}
    Foo(int a, int b) :high(a), wide(b){}

    Foo & operator++();//前置
    const Foo operator++(int);//后置调用前置

    friend const ostream& operator<< (const ostream&,const Foo&);
    //这样写 流对象之前加const常量限制符,会报错
private:
    int high;
    int wide;
};

const ostream& operator<< (const ostream& os, const Foo& foo)
{
    os << foo.high << " " << foo.wide;
    return os;
}

上面的写法 在流对象之前使用 const ,编译器会报错,报错提示如下:

image

错误提示原因是 输入流对象 没有匹配的 常量类型 输出。说白了就是 输出流操作 不能在输出 一个数据流而其本身没有任何变化。(如果理解不了这句话,可以先跳过,往后继续看,相信看完之后再来看这句话,就能理解了)

下面来试试去掉const常量修饰符之后的结果:

class Foo
{
public:
    Foo() :high(0), wide(0){}
    Foo(int a, int b) :high(a), wide(b){}

    Foo & operator++();//前置
    const Foo operator++(int);//后置调用前置

    friend ostream& operator<< (ostream&,const Foo&);
    //这是去掉const常量修饰符,正确的做法

private:
    int high;
    int wide;
};

ostream& operator<< (ostream& os, const Foo& foo)
{
    os << foo.high << " " << foo.wide;
    return os;
}

编译通过,没有报错。

为什么加上const 修饰符之后,就是错误的呢?const 是用来修饰不会改变的 对象或变量状态的常量修饰符。而此处不能在重载的流对象之前加 const 说明 Foo类的友元函数 输出流对象 之后改变了流对象本身的状态。

C++ primer 对此的描述是“读写IO对象会改变其状态,返回的引用不能是const“。

那么一个流对象,使用之后,其状态为什么被改变了呢?

我们先来想一下我们处理一个文本文件的场景:先打开一个文本文件,获得其句柄,通过该句柄可以对其读写操作(注意此处的读写操作,很像我们的流操作。其实C++的文件操作,标准化就是通过重载<<与>>进行流读写的)。文件读写通过两个文件指针,一个读指针,一个写指针,每次进行读或写操作,读写指针就会自动往后移动。注意这里,读写指针自动移动。这里就已经改变了文件的流对象 的状态。

同理,我们的屏幕输出流对象和键盘输入流对象,也有这么类似的一对自动移动的读写指针,每次进行流操作时,例如在屏幕打印一个字符,屏幕输出流对象的位置指针就会向后移动一个单位。这里就改变了流对象的状态。

下面引用一位网友对此形象的描述:河里的水流虽然看起来没有变化,但是有水流过,肯定有东西发生了变化(河床发生了侵蚀,沙子发生了沉积)。

posted on 2017-11-13 22:59 云中孤鹤 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/wangzhizhen/p/7828750.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值