24.若所有参数皆需类型转换,请为此采用non-member函数
正常情况下令classes支持隐式类型转换是糟糕的,但在建立数值类型时,一般要求classes支持隐式类型转换。
class Rational
{
public:
Rational(int numerator = 0, int denominator = 1);
int numerator() const;
int denominator() const;
const Rational operator* (const Rational & rhs) const;
private:
int m_numerator;
int m_denominator;
};
调用例子:
Rational r1(2, 3);
Rational r2(6, 8);
// 由于操作符*形参类型是Rational,所以就会调用构造函数构造Rational对象,从而实现隐式类型转换
Rational r3 = r1*2;
// 相当于 Ration r3 = r1.operator*(2);
// 但像下面这样调用就是错误的
r3 = 2 * r1; // 相当于 r3 = 2.operator*(r1);
从例子可知,当参数被列于参数列内,该参数才可以被隐式类型转换。
但若想支持乘法交换定律,那么就让operator*成为一个non-member函数,这样*左右参数都会被列入参数列内,从而执行隐式类型转换。
const Rational operator* (const Rational & lhs, const Rational & rhs)
{
return Rational(lhs.numerator()*rhs.numerator(), lhs.denominator() * rhs.denominator());
}
总结:如果你创建的类是与数据类型相关的,那么就要支持隐式类型转换,并且定义运算符后,如果要支持运算符左右的参数隐式类型转换,那么将该运算符定义为non-member函数。
PS:无论合适如果可以避免friend函数就该避免,因为friend函数带来的麻烦往往多余价值。