前言
</br>
前文曾说过,令classes支持隐式转换通常会带来风险,但这也有例外,比如当你建立的是一个数值类型。
问题实例
</br>
假设我们建立了一个有理数类,它允许整数隐式转换为有理数:
1 | class Rational{ |
接下来需要纠结的就是运算符到底是写为member还是non-member呢?
问题处理
</br>
首先考虑声明为member函数的情况:
1 | const Rational operator* (const Rational& rhs) const; |
那么很自然地,两个Rational对象可以很自由地相乘。但你会发现这个函数没法做到混合类型计算,比如说,一个int乘以一个ratioanl对象:
1 | res = oneHalf * 2;//正确,因为执行了隐式转换 |
不能编译的原因很简单,int并没有成员函数
operator*
。解决的方法也很简单,把operator*
声明为non-member函数即可:1 | const Rational operator* (const Rational& lhs,const Rational& rhs); |
如此一来,混合类型计算的问题就得到了完美解决,哪怕两个参数都不是Rational,但只要它们存在直接变为Rational对象的隐式转换即可顺利编译与运行。
friend函数
</br>
那运算符是否需要成为friend函数呢?答案也是否定的。friend函数可以直接访问内部数据,这大大降低了封装性。当然friend函数也有优点,但我们应该牢记:不能因为函数不该成为member,就自动让它成为friend.
总结
</br>
本节叙述的内容仅在OO领域内生效,当我们进入template领域并令Rational成为一个class template后,又会出现新的争议、解法、以及设计思路。
但至少在OO领域内我们应当牢记:如果某个函数的所有参数都可能需要进行类型转换,那么这个函数必须是个non-member.