读书笔记四
- 让接口容易被正确使用,不容易被误用
- 好的接口容易被正确的使用,不容易被误用。你应该在你的所有接口中努力达到这些性质。
- 促进正确使用的办法包括接口的一致性,以及与内置类型的行为兼容
- 阻止误用的办法包括建立新类型,限制类型上的操作,束缚对象值,消除客户的资源管理责任
- 设计class犹如设计type
- 宁以pass-by-reference-to-const替换pass-by-value
- 按值传递的消耗比按引用传递的消耗大。按引用传递的效率较高。
- 一般的内置类型的传递都是使用按值传递,当然这也不是绝对的。一般按值传递:内置类型或者是STL迭代器和函数对象
- 至于其他的都是最好用按引用传递来代替按值传递。
- 必须返回对象的时候不要想返回引用
- 绝对不要返回pointer或者reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,货返回pointer'或者rederence指向一个local static对象而有可能需要多个这样的对象。
- 绝对不要返回pointer或者reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,货返回pointer'或者rederence指向一个local static对象而有可能需要多个这样的对象。
- 将成员变量声明为private
- 宁以non-menber,non-friend替换member函数
- 由于面向对象要求尽可能封装,所以不用直接访问数据的非成员函数是比较好的。前面那条也说过最好是将成员变量声明为private,但是只有friend函数和成员函数可以访问private成员变量,所以为了封装性更好,更少的东西能够访问它,所以我们最好是用非成员函数和非friend'函数去访问成员变量
- 一个class中的非member函数可以是另一个namespace中的member函数
namespace webbrowserstuff{ class webbrowser{...} void clearbrowser(webbrowser &wb); }
- 若所有参数皆需类型转换,请为此采用non-member函数
- 问题产生:
class Rational{ public: Rational(int numerator = 0,int denominator = 1); int numerator()const; int denominator()const; private: ... };我想支持加减乘除这些运算,operator *等一些列方法,决定是该用member函数还是要non-member函数
写成成员函数
const Rational operator * (const Rational& rhs)const;
//测试用例
Rational one(1,8);Rational two(1,2);Rational result=one*two;//正确
result= one.opeartor*(2);//正确,编译器可以将2int类型的变量通过构造函数(non-explicit)变成rational对象,这里是隐式转化,如果构造函数不支持隐式转化,这个也是错的
result=2.operator*(one);//错误,因为上述那个成员函数并没有一个int,一个rational作为参数的*运算函数,调用失败,其实就是2不能转换成rational对象
写成non-member,支持每个实参执行隐式类型转换
class Rational{
...
};
const Rational operator *(const Rational &lhs,const Rational &rhs){
return Rational(lhs.numerator()*rhs.numerator(),lhs.denominator()*rhs.denominator());}
- 问题产生:
- 写出一个不抛出异常的swap函数
- 当std::swap对你的类型效率不高的时候,提供一个swap成员函数,并确定这个函数不抛出异常
- 如果你提供一个member swap,也应该提供一个non-member swap函数来调用前者。对于classes,也请特化std::swap