成员函数与非成员函数最大的差异是,成员函数可以是虚拟函数,而非成员函数不可以。所以如果你有一个函数需要动态绑定(直到执行时期再确定应该调用哪一个函数),你必须用虚拟函数,而此虚拟函数必须是成员函数。
假设f是想正确声明的函数,C是和它相关的类,有如下原则:
a、虚函数必须是成员函数。如果f必须是虚函数,就让它成为C的成员函数。
b、operator>>和operator<<决不能是成员函数。如果f是operator>>或operator<<,让f成为非成员函数。如果f还需要访问C的非公有成员,让f成为C的友元函数。
c、只有非成员函数对最左边的参数进行类型转换。如果f需要对最左边的参数进行类型转换,让f成为非成员函数。如果f还需要访问C的非公有成员,让f成为C的友元函数。
d、其它情况下都声明为成员函数。如果以上情况都不是,让f成为C的成员函数。
如果运算符被重载为非成员函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。
如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。
下面的例子*运算符只能用其一:
class Rational ///表现分数的类
{
///分子的乘法,当为友元函数;
friend const Rational operator*(const Rational& lsh,const Rational rhs)
{
//取用了Rational的private变量;
return Rational(lsh.numerator * rhs.numerator,
rsh.denominator * rhs.denominator)
}
public:
Ration(int numerator = 0,int denominator =1);
Const Rational operator*(const Rational& rhs) const;//当为成员函数;
Private:
Int numerator;//分子
Int denominator;//分母
}
rational onehalf(1, 2);
rational result
result = onehalf * 2; // 运行良好
result = 2 * onehalf; // 出错!因为是成员函数,左边参数不支持隐形转换。
当其变成非成员函数时:
//当为非成员函数;
const Rational operator*(const Rational& lsh,const Rational rhs)
{
}
rational onehalf(1, 2);
rational result
result = onehalf * 2; // 运行良好
result = 2 * onehalf; //运行良好,因为是非成员函数,左边参数支持隐形转换。
当为friend函数(最好少用):
rational onehalf(1, 2);
rational result
result = onehalf * 2; // 运行良好
result = 2 * onehalf; //运行良好,因为是非成员函数,左边参数支持隐形转换,且可取用Rational中的private变量。