解讀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++的文件操作,標准化就是通過重載<<與>>進行流讀寫的)。文件讀寫通過兩個文件指針,一個讀指針,一個寫指針,每次進行讀或寫操作,讀寫指針就會自動往后移動。注意這里,讀寫指針自動移動。這里就已經改變了文件的流對象 的狀態。

同理,我們的屏幕輸出流對象和鍵盤輸入流對象,也有這么類似的一對自動移動的讀寫指針,每次進行流操作時,例如在屏幕打印一個字符,屏幕輸出流對象的位置指針就會向后移動一個單位。這里就改變了流對象的狀態。

下面引用一位網友對此形象的描述:河里的水流雖然看起來沒有變化,但是有水流過,肯定有東西發生了變化(河床發生了侵蝕,沙子發生了沉積)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM