Declare non-member functions when type conversions should apply to all parameters
动机
通常来说,让一个类支持隐式是一个糟糕的设计,它会使得程序变得复杂。但在某些时候,我们需要隐式的转换,考虑一个有理数的类:
1 | class Rational{ |
如果希望支持算术运算符诸如加法,乘法,那么可以这样实现:
1 | class Rational{ |
但这种设计有个问题: 1
2
3
4
5
6
7
8
9
10
11
12
13Rational oneEighth(1, 8);
Rational oneHalf(1, 2);
Rational result = oneHalf * oneEighth; //可以通过
result = oneHalf * 2; //也可以通过,等同于
result = oneHalf.operator*(2);
//通过的原因,编译器构造了临时对象
const Rational temp(2);
result = oneHalf*temp;
//而如果是想要满足乘法交换律,则会失败:
result = 2 * oneHalf;
//因为2没有相应的class,也就没有operator*函数。当然编译器会尝试在命名空间内或者在global作用域内调用non-member operator*,而这也找不到
解决方法
当然,可以声明explicit
构造函数,这也就保证了一致性,但就无法满足了乘法运算。
为了解决这个问题,也满足了四则运算,我们可以构造一个non-member函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Rational{
...
};
//构造一个non-member函数
const Rational operator*(const Rational& lhs,
const Rational& rhs)
{
return Rational(lhs.numerator()*rhs.numerator(),
lhs.denominator()*lhs.denominator());
}
//这样,就都可以通过了
Rational result;
result = oneFourth * 2;
result = 2 * oneFourth;
这样,就基本解决问题了。。。。
建议
- 如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是一个non-member