4 设计与声明
~~~~~~~~~~~~~
4.1 让接口容易被正确使用,不易被误用
====================================
1. 许多客户端错误可以因为导入新类型而获得预防.
一旦使用了新类型,限制其值就顺其自然了.
2. 任何接口如果要求客户必须记得做某事,就是有着不正确使用的倾向,因为客户可能会忘记做那件事.
4.2 设计class犹如设计type
==========================
1. 几乎没有class都要求你面对以下几个问题
* 新的type的对象应该如何被创建和销毁?
* 对象的初始化和对象的赋值应该有什么样的差别?
* 新的type的对象如何被passed by value?
copy构造函数用来定义一个type的pass-by-value该如何实现
* 新type的合法值范围是什么?
* 你的新type是否继承至其他类,或者有其他类继承至新type类?
特别关系到函数的virtual和non-virtual的影响
* 你的新type需要转换为其他type吗?
如果你希望类型T1可以隐性转换为类型T2,可以
1) 在class T1内写一个类型转换函数(operator T2)
2) 在class T2内写一个non-explicit-on-argument的构造函数
* 什么样的操作符和函数对该type而言是合理的
* 什么样的标准函数应该被屏蔽(声明为private)
* 哪些类型可以存取type内成员?
这个问题帮助你决定成员的权限,也帮助你决定哪一个class或function是友元的,以及它们嵌套于另一个之内是否合理.
* 什么是新type的未声明接口( *什么意思??* )
* 你想定义的是一个新type还是整个types家族,或许你应该定义的是一个新的class template
* 你真的需要一个新的type吗?
如果只是定义新的derived class以便为既有的class添加功能,那么说不定单纯定义一个函数就能达到目标
4.3 以pass-by-reference-to-const替换pass-by-value
==================================================
1. 节省开销
2. 解决子类的切割问题
3. 对于内置类型STL的迭代器和函数对象,pass-by-value比pass-by-reference-to-const效率高
4.4 宁以non-member-non-friend函数替换member函数
================================================
1. 由于member函数可以访问类中private数据,而non-member-non-friend函数不能访问类的private函数,因此non-member-non-friend函数的封装性强过member函数
2. friend函数的封装性与member函数相同,他们都能访问类的private数据
3. 在C++,比较自然的做法是让non-member-non-friend函数与类放在同一个命名空间中,这也是C++标准程序库的组织方式.
4.5 若所有参数都需要类型转换,请为此采用non-member函数
======================================================
1. 只有当参数被列于参数列内,这个参数才是隐式类型转换的合格参与者.而member函数所在对象(this对象)也因此并不能被隐式转换.
因此,为了使用对象的隐式转换功能,可以把this作为non-member函数中的一个参数.
4.6 当std::swap的效率不够高时,考虑写出一个不抛异常的swap函数
=============================================================
1. 可以在member的swap函数中调用std::swap对private权限的成员进行互换
2. 只能对class templates进行偏特化,而function templates不能进行偏特化,只能进行全特化.
3. 如果你打算偏特化一个function template时,惯常做法是简单的为它添加一个重载版本
4. 严格来说,std是个特殊的命名空间,客户可以全特化std内的templates,但不能添加新的templates或classes或functions或任何东西到std里头.
std的内容理论上完全由C++标准委员会决定.
5. 如果swap的缺省实现提供的效率可接受的话,就不用做任何事了.
如果swap缺省实现效率不足,那么试着做以下事情
1) 提供一个public swap成员函数,让它高效地置换你的类型的两个对象值.这个函数不能抛出异常
2) 让你的class货template所在的命名空间内提供一个non-member swap,并令它调用上述的swap成员函数
3) 如果你编写一个class,为你的class特化std::swap.并令它调用你的swap成员函数.
本文出自 “暗日” 博客,请务必保留此出处http://darksun.blog.51cto.com/3874064/1144749