bool operator==(const Rational& lhs, const Rational& rhs); Rational a, b, c, d; if ((a*b) == (c*d)){} else{}
上面代码里的if后的条件总是成立的,因为a*b返回的一个static对象的引用,而c*d返回的是同一个static对象的引用,所以永远相等。
所以,我们最终的选择是通过pass-by-value来返回新的对象。
const Rational operator*(const Rational& lhs, const Rational& rhs) { return Rational(lhs.n*rhs.n, lhs.d*rhs.d); }
条款22:将成员变量声明为private
首先是代码的一致性(调用public成员时不用考虑是成员还是函数)。
其次封装性,都写成函数进行访问可以提供以后修改访问方法的可能性,而不影响使用方法。另外,public影响的是所有使用者,而protected影响的是所有继承者,都影响巨大,所以都不建议声明成员变量。
切记将成员变量声明为private。这可赋予客户访问数据的一致性、可细微划分访问控制、允诺条件获得保证,并提供class作者以充分的实现弹性。
protected并不比public更具封装性。
条款23:宁以non-member、non-friend替换member函数
想像有个class用来表示网页浏览器。这样的class可能提供的众多函数中,有一个用来清除下载元素的高速缓冲区(cache of downloaded elements)、清除访问过的URLs的历史记录、以及移除系统中所有的cookies。
class WebBrowse { public: void clearCache(); void clearHistroy(); void removeCookies(); };
许多用户想一个函数来执行整个动作,因些WebBrowse也提供这样一个函数:
class WebBrowse { public: //... void clearEverything();//依次调用clearCache(),clearHistory(),removeCookies() };
当然这个功能也可以由一个non-member函数来完成:
void clearEverything(WebBrowse& wb) { wb.clearCache(); wb.clearHistory(); wb.removeCookies(); }
那么哪一个比较好呢?
根据面向对象守则要求,数据以及操作的那些函数应该捆绑在一块,这意味着member函数是较好的选择。不幸的是这个建议不正确。面向对象要求数据应该尽可能被封装。
member函数带来的封闭性比non-member函数低,因为它并不增加“能够访问class内之private成份”的函数数量。
此外,提供non-member函数可以允许对WebBrowse相关机能能有较大的包裹弹性,而那最终导致较低的编译相依度,增加WebBrowse的可延伸性。