设计class要带着和“语言设计者当初设计语言内置类型时”一样的谨慎来设计class。
class也是一个types,好的types具备自然的语法,直观的语义,以及一或多个高效实现品。
class设计checklist:
<!--[if !supportLists]-->1、 <!--[endif]-->新type的对象应该如何创建和销毁?
<!--[if !supportLists]-->2、 <!--[endif]-->对象的初始化和对象的赋值该有什么样的差别?这决定了class的构造函数和赋值(assignment)操作符的行为,以及其间的差别,很重要的是不要混淆了初始化和赋值。
<!--[if !supportLists]-->3、 <!--[endif]-->新type的对象如果被passed by value(以值传递),意味着什么?copy的构造函数定义了一个type的pass-by-value该如何实现。
<!--[if !supportLists]-->4、 <!--[endif]-->什么是新type的合法值?对class的成员变量而言,通常只有某些数值集是有效的。那些数值集决定了你的class必须维护的约束条件,也就觉得了你的成员函数(特别是构造函数,赋值操作符以及所谓的seter函数)必须进行的错误检查。
<!--[if !supportLists]-->5、 <!--[endif]-->你的新的type需要配合某个继承体系吗?如果你继承自某些既有的class,你就受到那些class的设计的束缚,特别是他们的函数是virtual或no-virtual的影响。如果允许其他的classes继承你的class,那么你所声明的函数——尤其是析构函数——是否为virtual。
<!--[if !supportLists]-->6、 <!--[endif]-->你的新type需要什么样的转换?如果你希望类型T1之物被隐式转换为T2之物,就必须在T1内些一个类型转换函数operator T2或在T2内部写一个non-explicit-one-argument(可被单一实参调用)的构造函数。如果你只允许explicit构造函数存在,就得写出专门负责转换的函数,且不得为类型转换操作符(type conversion operator)或non-explicit-one-argument构造函数。尽量避免隐式转换。
<!--[if !supportLists]-->7、 <!--[endif]-->什么样的操作符和函数对此新的type而言是合理的?
<!--[if !supportLists]-->8、 <!--[endif]-->什么样的标准函数应该被驳回?那些正是你声明为private的函数,比如,构造函数可能会声明为private,也就是不允许进行new操作。
<!--[if !supportLists]-->9、 <!--[endif]-->谁该取用type的成员?这可以决定哪些成员是public,那些成员是protected,那些为private,也可以决定哪些classes和function是friends。
<!--[if !supportLists]-->10、 <!--[endif]-->声明式新type的未声明接口?
<!--[if !supportLists]-->11、 <!--[endif]-->你的新type有多么的一般化?或许你其实并不是定义一个新type,而是定义一整个types家族。果真如此你就不应该定义一个新的class,而应该定义一个新的class template。
<!--[if !supportLists]-->12、 <!--[endif]-->你真的需要一个新的type吗?如果只是定义新的derived class以便为既有的class添加新机能,那么说不定单纯定义一个或多个non-members函数或template更能达到目的。