21.通过重载避免隐式转换

问题实例

1
2
3
4
5
6
7
8
9
10
class UPInt {// unlimited precision integers
public:
UPInt();
UPInt(int value);
...
};
const UPInt operator+(const UPInt& lhs, const UPInt& rhs);
UPInt upi1, upi2;
...
UPInt upi3 = upi1 + upi2;

这段程序不足为奇,再接着看如下表达式:

1
2
upi3 = upi1 + 10;
upi3 = 10 + upi2;

这也能够运行,原因在于隐式转换建立临时对象把int转成了UPInt(More Effective C++ 5)。显然,这是需要一定的开销。


解决方案

 
其实我们并不是想要做类型转换,我们只不过是想让int能和upint相加而已,既然当前不具备可适配性,那我们完全可以通过重载函数适配所有可能出现的情况:

1
2
3
const UPInt operator+(const UPInt& lhs,const UPInt& rhs);
const UPInt operator+(const UPInt& lhs,int rhs);
const UPInt operator+(int lhs,const UPInt& rhs);

如此则不会产生任何由于隐式转换所带来的开销。
看起来我们忘记了做两个int相加返回UPInt的operator+重载,但是实际上我们无法这么做,因为c++规定每一个operator重载函数都必须有一个用户自定义类型作为参数,否则容易出现混乱的修改。


总结

 
利用重载避免生成临时对象的方法不仅仅只适用于操作符,而是适用于任何可能产生隐式转换之处。
不过,必须谨记80-20准则(More Effective C++ 16)。我们没有必要实现大量的重载函数,除非你有理由确信整体效率会有显著的提高。