1.你的类需要一个构造函数吗?
有的类太简单,它们的结构就是它们的接口,所以不需要构造函数。但是,我们现在主要关心的是哪些足够复杂的类,它们需要构造函数来隐藏它们内部工作方式。
2.你的数据成员是私有的吗?
通常使用公有的数据成员不是什么好事,因为类设计者无法控制何时访问这些成员。
3.你的类需要一个无参的构造函数吗?
如果一个类已经有了构造函数,而你想声明该类的对象可以不必显示地初始化它们,则必须显示地写一个无参的构造函数。
4.是不是每个构造函数初始化所有的数据成员?
构造函数的用途就是用一种明确定义的状态来设置对象。对象的状态由对象的数据成员进行反映。因此,每个构造函数都要负责为所有的数据成员设置经过明确定义的值。如果构造函数没有做到这一点,就很可能导致错误。
当然,这种说法未必总是正确的。有时类有一些数据成员,它们只在它们的对象存在了一定时间之后才有意义。
5.类需要析构函数吗?
不是所有有构造函数的类都需要析构函数。应该问一问该类是否分配了资源,而这些资源又不会由成员函数自动释放,这就足够了。特别是那些函数里包含了new表达式的类,通常在析构函数中加上相应的delete表达式,所以会需要一个析构。
6.类需要一个虚析构函数吗?
决不会用作基类的类是不需要虚析构函数的:任何虚函数只在继承的情况下才有用。
struct B{
string s;
};
struct D : public B
{
string t;
};
int main()
{
B *bp = new D;
delete bp; //除非B有一个虚析构函数,否则将调用错误的析构函数。
}
这里即使B没有虚成员函数,甚至根本没有任何成员函数,也必须有一个虚析构函数,否则delete会出错。
struct B{
string s;
virtual ~B() {}
};
虚析构函数通常是空的。
7.你的类需要复制构造函数吗?
关键在于复制该类的对象是否就相当于复制其数据成员和基类对象。如果并不相当,就需要复制构造函数。
8.你的类需要一个赋值操作符吗?
如果需要复制构造函数,同理多半也需要一个赋值操作符。如果不想用户能够设置类中的对象,就将赋值操作符私有化(c++11中使用=delete)。
9.你的赋值操作符能正确地将对象赋给对象本身吗?
//正确的实现方法1
String& String::operator=(const String &s)
{
if(&s != this){
delete []data;
data = new char[strlen(s.data) + 1];
strcpy(data, s.data);
}
return *this;
}
//正确的实现方法2
String& String::operator=(const String &s)
{
char* newdata = new char[strlen(s.data) + 1];
strcpy(newdata, s.data);
delete []data;
data = newdata;
return *this;
}
10.你的类需要定义关系操作符吗?
如果你的类逻辑上支持相等操作,那么提供operator==和operator!=就可能会很有好处。类似地,如果你的类的值有某种排序关系,那就可能会想提供余下的关系操作符。
11.删除数组时你记住了用delete[]吗?
12.记得在复制构造函数和赋值操作符的参数类型中加上const了吗?
复制对象不会改变原对象。所以要加const。
复制构造函数:X::X(const X &x)
赋值构造函数:X::operator(const X &x)
13.如果函数有引用参数,它们应该是const引用吗?
只有当函数想改变参数时,它才应该有不用const声明的引用参数。
14.记得适当地声明成员函数为const的了吗?
如果确信一个成员函数不能修改它的对象,就可以声明它为const,这样就可以把它用于const对象了。