Item18:让接口易于使用,难于误用
Make interfaces easy to use correctly and hard to use incorrectly.
- shared_ptr定制删除器可以防范DLL问题(对象在一个DLL中创建,却在另一个DLL中销毁),自动解除互斥锁等。
- 对参数的范围做合理的检查
Item19:设计类型需要考虑周全
Treat class design as type design.
Item20:尽量以pass-by-reference-to-const替换pass-by-value
Prefer pass-by-reference-to-const to pass-by-value.
- 高效
- 避免切割问题,对象赋值后被切割,仅剩Base部分
- reference往往以指针实现,因此除了(当参数为内置类型,STL迭代器和函数对象时)pass-by-value比较适当,其余的用pass-by-reference-to-const比较好。
Item21:必须返回对象时,别妄想返回引用
Don’t try to return a reference when you must return an object.
- 不要返回pointer或reference指向一个local stack对象(离开作用域便失效)
- 不要返回reference指向一个heap_allocated对象(无法删除)
- 不要返回pointer或reference指向一个local static对象(对pointer或reference的值进行比较可能是指向同一个local static而导致永远为true)
Item22:将成员变量声明为private
Declare data members private.
通过函数访问可限制访问性,内部数据调整也不会影响现有的代码,python property便灵活的支持了这种特性。
Item23:宁以非成员非友元的函数替换成员函数
Prefer non-member non-friend functions to member functions.
避免增加原生数据的访问,增强封装性,例。
//清理浏览器,通过外部函数调用四个函数进行清理
browser.clear_cookie();
browser.clear_history();
browser.clear_download_files();
browser.clear_url();
不会影响class原有的封装性。
Item24:若所有参数皆需类型转换,请为此采用non-member函数
Declare non-member functions when type conversions should apply to all parameters.
如运算符重载:
Rational r(1, 2);
Rational r2 = r * 1; //成员时true,非成员true
r2 = 1 * r; //成员则false,非成员true
operator *若为成员函数,则左运算值必须为Rational类型,否则错误;operator *若为非成员函数,则两个运算值只要能转换成Rational类型,都可以进行运算。
Item25:考虑写一个不执行异常的swap
Consider support for a non-throwing swap
- 当类使用pimpl(pointer to implementation)时,需要实现自己的swap以高效进行交换(直接交换成员指针而无需创建临时对象)
- 实现non-member-swap,其内部调用member-swap,member-swap内部使用using std::swap交换指针