5.2.4 成员运算符重载函数和友元运算符重载函数的比较
(1)对双目运算符而言,成员运算符重载函数参数表中含有一个参数,而友元运算符重载函数参数表中有两个参数;对于单目运算符而言,成员运算符重载函数参数表中没有参数,而友元运算符重载函数参数表中有一个参数。
(2)双目运算符一般可以被重载为友元运算符重载函数或成员运算符重载函数,但有一种情况必须使用友元函数。
例如,如果将一个复数与一个整数相加,可用成员运算符重载函数"+"运算符:
Complex operator+(int a)
{
return (real+a,imag);
}
若com和com1是类Complex的对象,则以下语句是正确的;
com = com+100; //正确,运算符+的左侧是类对象
这条语句被C++编译系统解释为:
com = com.operator(100);
由于对象com是运算符"+"的左操作数,所以它可以调用"+"运算符重载函数operator+,
执行结果是对象com的数据成员real被加上一个整数100.
然而,以下语句就不能工作了:
com = 100+com; //运算符+的左侧是整数
这条语句被C++编译系统解释为:
com = 100.operator(com);
由于运算符"+"的左操作数是一个整数100,而不是该类的对象。编译时将会出错,因为整数100不能调用成员运算符重载函数。
如果定义以下的两个友元运算符重载函数
friend Complex operator+(Complex com,int x) //运算符+的左侧是类的对象,右侧是整数
{
return Complex(com.real+x,com.imag);
}
friend Complex operator+(int a,Complex com) //运算符+的左侧是整数,右侧是类的对象
{
return Complex(a+com.real,com.imag);
}
当一个复数与一个整数相加时,无论整数出现在左侧还是右侧,使用友元运算符重载函数都能得到很好的解决。这就解决了使用成员运算符重载函数时,由于整数出现在运算符+的左侧而出现的错误。
//例5.7 使用友元运算符重载函数实现一个复数与整数的相加。
#include<iostream> using namespace std; class Complex{ public: Complex(int r=0,int i=0) { real = r; imag = i; } void print(); friend Complex operator+(int a,Complex &c2); //声明友元运算符重载函数,+的左侧是整数,右侧是类的对象 friend Complex operator+(Complex c1,int a);//声明友元运算符重载函数,+的右侧是整数,左侧是类的对象 private: int real; int imag; }; Complex operator+(int a,Complex &c2) //定义友元运算符重载函数,+的左侧是整数,右侧是类的对象 { Complex temp; temp.real = a+c2.real; temp.imag = c2.imag; return temp; } Complex operator+(Complex c1,int a)//定义友元运算符重载函数,+的右侧是整数,左侧是类的对象 { Complex temp; temp.real = c1.real+a; temp.imag = c1.imag; return temp; } void Complex::print() { cout<<real<<"+"<<imag<<'i'<<endl; } int main() { Complex co1(30,40),co2(30,40),co3; co1.print(); co3=100+co1; //co3=operator+(100,co1); co3.print(); co3=co2+100; //co3=operator+(co2,100); co3.print(); return 0; }
(3)成员运算符函数和友元运算符函数都可以用习惯方式调用,也可以用它们专用的方式调用。
表5.2 运算符函数调用形式
------------------------------------------------------------------------------------------
习惯调用形式 友元运算符重载函数的调用形式 成员运算符重载函数的调用形式
a+b operator+(a,b) a.operator+(b)
-a operator-(a) a.operator-()
a++ operator++(a,0) a.operator++(0)
------------------------------------------------------------------------------------------
(4)C++大部分运算符既可以说明为成员运算符重载函数,又可以说明为友元运算符重载函数。
一般而言,对于双目运算符,将它重载为友元运算符重载函数比重载为成员运算符函数便于使用。
对于单目运算符,则选择成员运算符重载函数比较好。
如果运算符所需要的操作数(尤其是第一个操作数)希望有隐式类型转换,则运算符重载必须使用
友元函数,而不能使用成员函数。
a.对于单目运算符,建议选择成员函数
b.对于运算符"=、()、[]、->"只能作为成员函数
c.对于运算符"+=、-=、/=、*=、/=、!=、~=、%=、<<=、>>=",建议重载为成员函数
d.对于其他运算符,建议重载为友元函数。