C++標準庫筆記:13.12.3 以輔助函數完成I/O

如果執行IO操作符時需要存取對象的私有成員,通常有以下兩種方法:

使用輔助函數

IO操作符應該將實際任務委派給輔助的成員函數。這種技術允許具有多態性,如下:

class Fraction
{
public:
    Fraction( int nNumerator = 0, int nDemominator = 1 )
        :m_nNumerator( nNumerator ), m_nDemominator( nDemominator )
    {}

    //輔助輸入輸出函數
    virtual void PrintOn( std::ostream& strm ) const
    {
        strm << m_nNumerator << '/' << m_nDemominator;
    }
    virtual void ScanFrom( std::istream& strm )
    {
        strm >> m_nNumerator;
        strm.ignore(); //ignore '/'
        strm >> m_nDemominator;
    }

private:
    int m_nNumerator;       //分子
    int m_nDemominator;     //分母
};

std::ostream& operator << ( std::ostream& os, const Fraction& f )
{
    f.PrintOn( os );
    return os;
}

std::istream& operator >> ( std::istream& in, Fraction& f )
{
    f.ScanFrom( in );
    return in;
}

設置IO操作爲類的友元函數

訪問類的私有成員,也可以將IO操作符函數設計爲類的友元函數

class Fraction
{
    friend std::ostream& operator << ( std::ostream&, const Fraction&);
    friend std::istream& operator >> ( std::istream&, Fraction& );
public:
    Fraction( int nNumerator = 0, int nDemominator = 1 )
        :m_nNumerator( nNumerator ), m_nDemominator( nDemominator )
    {}


private:
    int m_nNumerator;       //分子
    int m_nDemominator;     //分母
};

std::ostream& operator << ( std::ostream& os, const Fraction& f )
{
    os << f.m_nNumerator << '/' << f.m_nDemominator;
    return os;
}

std::istream& operator >> ( std::istream& in, Fraction& f )
{
    in >> f.m_nNumerator;
    in.ignore(); //ignore '/'
    in >> f.m_nDemominator;
    return in;
}

對比

如果你的類不會作爲其他類的基類,以上兩種方法都一樣。
否則的話,一旦用上繼承,使用friend的方法就有很大的侷限性。friend函數不能成爲虛函數,所以程序可能會調用錯誤的函數。例如,某個基類引用實際指向一個派生類引用,並補當作input操作符的參數,則被調用的將是基類的操作符。爲了避免出現這種情況,繼承類不得實作自己的IO操作符,並且還要顯示調用(因爲不是虛函數)。
因此,使用第一種方法通用的多,儘管你在其它文件或書籍上看到的絕大多數例子使用的是friend函數,你最好將第一種方法視爲標準作法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章