有些运算符只能用友元函数(全局函数)重载,无法使用成员函数重载,如:
class Complex
{
public:
Complex()
{
}
Complex(int a,int b)
{
this->a = a;
this->b = b;
}
friend void operator << (ostream & out, Complex C);
//这里不加引用就会报函数已删除的错误,原函数返回值当左值必须返回一个引用,见图1
protected:
private:
int a ;
int b ;
};
void operator << (ostream &out, Complex C)
{
out << C .a << C.b ;
}
void main ()
{
Complex c1 (1, 2);
cout << c1 ;
system("pause" );
}
图1,不加引用报错:
如改成员函数:
则应写为
cout. operator <<(RightOp)
“<<”重载如果想放在成员函数中实现,那就意味着必须作为cout的成员函数,但是cout已经封装好,这里明显是不现实的。
那如果放在Complex成员函数中呢?如:
class Complex
{
public:
Complex()
{
}
Complex(int a,int b)
{
this->a = a;
this->b = b;
}
void operator << (Complex C)
{
}
protected:
private:
int a ;
int b ;
};
我们知道其中隐含的this指针指向的对象如 c1 必须作为左操作数,而在重载函数(void operator << (RightOp))之中他自身又必须作为右操作数,将变成 c1 << c1 这样是不正确的。
所以有些运算符只能用只能用友元函数(全局函数)重载。
引申(链式法则):
上面重载操作时只是采用了简单处理,让其返回void类型
void operator << (ostream &out, Complex C)
{
out << C .a << C.b ;
}
但是如果遇到的情况稍微复杂一点,必然会出现一些问题,如:
cout << c1 << "abcd";
因为上述重载中左操作数为cout,右操作数为c1,而后半部分左操作数为c1,右操作数为“abcd”,虽然我们知道“abcd”常量字符串会返回一个字符串指针,但是此处还可能是跟着各种变量等,所以为了避免反复构造不同的重载,这里我们可以使用链式法则,这样即使后面接 endl 或者其他Complex对象,依然可以正常调用。
为了解决这个问题,我们把问题先拆分成两个简单步骤:
operator << (cout ,c1); //转化为函数调用形式
cout<< "abcd";
如果想要链式的进行,则使(operator << (cout ,c1) ; )返回cout 即可。
(cout << c1 )<< “abcd”; ====> cout<< “abcd”;
这样即可链式的传递下去。
具体重载方法:
ostream& operator << (ostream &out, Complex C)
{
out << C .a << C.b ; //此处可以不加endl,因为调用时使用 cout << c1 << endl; 比较符合习惯
return out ;
}