题记:摘自C++沉思录(p37-p44),感觉不错,分享之。在摘录的过程中,条目没有修改,每个条目下的描述有所改动,敬请知晓,另外,转载请注明出处。
核查表并不是任务清单。它的用途是帮助你回忆起可能会忘掉的事情,而不是来约束你。如果只是盲目地按照核查表的要求按部就班地做,到头来可能还是会忘记一些事情。知道了这一点之后,请看下面关于定义类时要弄清楚的一些问题。这些问题都没有确切的答案,关键是要提醒你思考它们,并确认你所作的事情是出自于有意识的决定,而非偶然事件。
* 你的类需要一个构造函数吗?
是否需要,要看具体情况,结构比较简单的类,不需要构造函数。当我们需要使用那些足够复杂的类时,需要构造函数来隐藏它们的内部工作方式。
* 你的数据成员是私有的吗?
通常使用公有的数据成员不是什么好事情,因为类的设计者无法控制何时访问这些成员。
* 你的类需要一个无参的构造函数吗?
如果一个类已经有了一个构造函数,而你想声明该类的对象可以不必显式地初始化它们,则必须显式地写一个无参的构造函数。
* 是不是每个构造函数初始化所有的数据成员?
构造函数的用途就是以一种明确的状态来设置对象,而对象的状态由对象的数据成员反映。并非所有的数据成员都需要立即初始化,有时,类会有一些数据成员,它们只在它们的对象存在了一定时间之后才有意义。
* 类需要析构函数吗?
需要深入考虑一个类要做些什么,那么该类是否需要析构函数的问题就十分明显了。应该问一问该类是否分配了资源,而这些资源有不会由成员函数自动释放,这就足够了。
* 类需要一个虚析构函数吗?
有些类需要虚析构函数只是为了声明它们的析构函数是虚的。决不会用作基类的类是不需要虚析构函数的:任何虚函数只有在继承的情况下才有用。
* 你的类需要复制构造函数吗?
复制该类的对象是否就相当于复制其数据成员和基类对象,这是问题的关键,如果并不相当,就需要复制构造函数。如果类在构造函数内分配资源,则可能需要显式的复制构造函数来管理资源。有析构函数(除了空的虚析构函数外)的类通常是用析构函数来释放构造函数分配的资源,这通常也说明需要一个复制构造函数。
* 你的类需要一个赋值操作符吗?
如果需要复制构造函数,同理多半也会需要一个赋值操作符。如果不想用户能够设置类中的对象,就将赋值操作符私有化。
* 你的赋值操作符能正确地将对象赋给对象本身吗?
自我赋值时,要保证不会把自己释放,通常使用if(this != &r)来判断。
* 你的类需要定义关系操作符吗?
由于C++支持模板,所以通用库也逐渐开始包含容器类了。这些类提供了关于诸如列表,集合和图等数据结构的泛型定义。这些容器依赖于它们所包含的元素类型的操作。通常要求容器能够判断两个值是否相等。还常常需要容器具有判断一个值是否大于或者小于另一个值的能力。
因此,如果你的类逻辑上支持相等操作,那么提供operator==和operator!=就可能会很有好处。类似地,如果你的类的值有某种排序关系,那么就可能会提供余下的操作符。只要有人想创建你的类型的有序集合,你就必须提供关系操作符。
* 删除数组时你记住了用delete[]了吗?
由于历史的原因以及编译器优化,这里提供delete[]语法,具有很高的效率,而使用这种格式,仍然是一种很好的习惯。
* 记得在复制构造函数和赋值操作符的参数类型中加上const了吗?
复制对象不会改变源对象,使用const进行限定,是十分好的风格,而赋值也一样。
* 如果函数有引用参数,它们应该是const引用吗?
只有当函数想改变参数时,它才应该有不用const声明的引用参数。
* 记得适当地声明成员函数为const的了吗?
如果确信一个成员函数不用修改它的对象,就可以声明它为const,这样就把它用于const对象了。