一、关于流运算符(<<、>>)的重载问题###
首先考察一个实部虚部为double类型的复数complex类:
class complex
{
public:
complex (double r = 0, double i = 0): re (r), im (i) { }
//……
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;
//……
};
对<<
操作符进行重载,使cout
能够以“(x + yi)”的格式输出complex对象时,可以这么做:
ostream& operator<<(ostream& os, const complex& c)
{
os << "(" << c.real() << " + " << c.imag() << "i)";
return os;
}
如果不想调用real()
和imag()
,想直接访问re
和im
这两个私有成员,那么我们要把operator <<
定义为complex类的友元函数:
class complex
{
//……
//在complex类里声明友元
public:
friend ostream& operator<<(ostream& os, const complex& c);
//……
};
ostream& operator<<(ostream& os, const complex& c)
{
os << "(" << c.re << " + " << c.im << "i)";
return os;
}
那么,为什么不能把<<
运算符直接重载为complex类的成员函数呢?这样不用声明友元不也可以访问私有成员了吗?
假如真的这么做了,那么我们的代码应该是这个样子:
class complex
{
public:
//……
ostream& operator<<(ostream& os, const complex& c);
//……
};
但是这是成员函数呀,前面还应该有个隐含的this
指针才对,<<
是双目运算符,只能接收两个参数,所以这么写不对;
那我们重载<<
的目的就是为了将complex对象的输出格式放到cout
里,所以只好改成这样:
class complex
{
public:
//……
ostream& operator<<(ostream& os);
//……
};
//<<的实现
ostream& complex::operator<<(ostream& os)
{
os << "(" << c.re << " + " << c.im << "i)";
return os;
}
然后用的时候,因为成员运算符函数固定左值为该类的对象,所以只好写成这样:
complex c1(1, 2);
c1 << cout;
和我们平时用的cout << c1
这样格式方向相反,非常别扭,
而且如果要实现连续输出cout << c1 << c2 << ......
,呃,不对,现在的例子应该是...... << c2 << c1 << cout
,除了最右边那个<<
可以调用,其他的<<
因为接收的参数是complex类型,所以我们还要进行一次重载。种种麻烦说明,还是老老实实把<<
重载写在类外面,或者声明友元好了。