条款18:努力让接口完满(complete)且最小化
即对于clients可能希望完成的任何合理工作,class都应该提供一个合理的方法来完成
最小化就是尽可能的让函数个数最少
条款19:区分member functions,non-member functions和friend funcitons三者
member functions和non-member functions之间最大的差异是,member functions可以是虚拟函数而non-member functions不可以。
程序一:
class Rational{
.... //不含operator*
};
//在类之外声明operator*函数
const Rational operator*(const Rational& lhs,
const Rational& rhs)
{
return Rational(lhs.numerator()*rhs.numerator(),
lhs.denominator()*rhs.denominator());
}
Q1、为什么作为全局函数,而不放在类里面
当我们这么在类里面定义operator*时
class Rational{
public:
...
const Rational operator*(const Rational& rhs) const; //*this为默认的lhs
};
现在使用这个类
Rational oneEighth(1,8);
Rational oneHalf(1,2);
Rational result = oneHalf * oneEighth; => result = oneHalf.operator*(oneEighth)
Rational result = result * oneEighth; => result = result.operator*(oneEighth)
以上都可以实现,但当混合运算时
(1)混合运算-1
result = oneHalf*2; //可以 =>result = oneHalf.operator*(2)
why? => 编译器进行了隐式型别转换,于是上面的运算变成了这样
const Rational tmp(2);
result = oneHalf*tmp;
(2)混合运算-2
result = 2*oneHalf; //不可以 =>result = 2.operator(oneHalf);
why? =>参数是对了,但整数2没有相应的class,也就没有operator* member function,更不支持隐式转换(只有出现在参数表上的参数享受这项服务,*this并不在服务对象之列)。编译器会在全局范围搜索如下形式的non-member operator*:result = operator*(2,oneHalf); 并不存在这样的operator*。所以失败。
实验:假如类内有operator*(rhs) 类外也有全局的operator*(lhs,rhs),会优先调用哪个呢?
实验证明,不能两个同时写,那就把operator*提出来吧,最为全局函数。
Q:如何让类不支持隐式型别转换呢?
A:在构造函数前加关键字explicit,这样混合运算-1也不可以实现了。
A1:正因为希望支持混合式运算,所以用全局函数,使得左右参数都