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函数,你最好将第一种方法视为标准作法

猜你喜欢

转载自blog.csdn.net/s634772208/article/details/73087316