C++沉思录(Ruminations On C++)读书笔记1.如何定义一个完整的类
作者: 2006-4-27 12:19
C++ 哲学:只为用到的东西付出代价
定义一个类时必须搞清楚的几个问题:
-
需要构造函数吗?
如果答案为 no,那么很可能你需要定义的只是一个结构,而不是一个类,因为构造函数的用途是用一种明确定义的状态来设置对象。
-
数据成员是私有的吗?
一般来说,如果数据成员为公有,你很难控制这些成员何时被访问。
-
需要一个无参数的构造函数吗?
如果一个类已经有了构造函数,而你想声明该类的对象时不必显示地初始化它们,则必须显示地写一个无参数的构造函数。(特别是当你需要生成这个类的对象数组时!)
-
每个构造函数是否都对所有数据成员进行了初始化了?
对象的状态由对象的数据成员反映,因此每个构造函数都有负责为所有的数据成员设置经过明确定义的值。如果某个构造函数没有做到这一点,就很可能导致错误。(当然,这种说法未必总是正确的。因为有时,某些数据成员,只有在该对象存在了一定的时间后才有意义。)
-
需要析构函数吗?
并不是所有的类都需要析构函数的。一般来说,如果一个类分配了资源,并且这些资源不会被成员函数自动释放,那么这个类就需要一个析构函数。
-
需要一个虚析构函数吗?
任何不作为基类的类是不需要虚析构函数的,虚析构函数只有在继承的情况下才有用。当可能发生 delete 一个类型为基类的指针,可实际上该指针代表的是一个子类的对象,这个基类定义时需要一个虚析构函数。
-
需要一个复制构造函数吗
如果用类缺省的复制构造函数复制该类的对象时,如果能完整复制该类的数据成员和基类对象,就不需要复制构造函数,否则就需要。特别是,如果你的类在构造函数内分配了资源,或者在成员函数中分配了资源,则很可能需要一个显示的复制构造函数来管理资源。有析构函数(除了空的析构函数外)的类通常是用析构函数来释放资源,这通常也说明需要一个复制构造函数。
-
需要一个赋值操作符吗?
如果你的类需要复制构造函数,多半也需要一个赋值操作符。当然,如果你不想用户设置类中的对象,可以将赋值操作符声明为私有的。
-
赋值操作符能正确地将对象赋给对象本身吗?
自我赋值是常犯的错误!赋值总是用新值取代目标对象的旧值。如果原对象和目标对象是同一个,而我们又奉行“先释放旧值,再复制新值”的原则,那么就可能在还没有实施复制之前就把原对象销毁了!
-
需要定义关系操作符吗?
如果你的类需要放入 stl 的容器中,很可能需要定义关系操作符。把一个新对象加入容器中,某些容器,需要把新对象与容器里已有的对象进行比较,比如进行相等比较,进行大小比较。因此,如果类逻辑上支持相等操作,那么提供 operator== 和 operator!= 就会很有好处。类似,如果类的值有某种排序关系,你就可以提供 operator< 或者 operator> 等关系操作符。只要这些容器需要创建你的类的有序集合,你就必须提供关系操作符。
-
删除数组时记住用 delete[] 了吗?
在删除任何类型的数组时使用 delete[] 是一种很好的习惯。
-
在复制构造函数和赋值构造函数的参数类型中加上 const 了吗?
这是某些 C++ 著作中也会犯的错误!
如果函数有引用参数,只有在函数想改变函数的输入参数时,才应该不用 const 声明该引用参数!通常这个会被改变的输入参数也肩负着输出参数的角色。
-
记得适当地声明成员函数为 const 了吗?
如果确信一个成员函数不用修改它的对象,就可以声明它为 const。
-
一个需要上述所有特性类定义的例子
// 声明
class A{
public:
A();
virtual ~A();
A(const A& s);
A& operator=(const A& s);
bool operator==(const A& s) const;
bool operator!=(const A& s) const;
bool operator<(const A& s) const;
};
// 实现
A::A(){
// todo...
}
A::~A(){
// todo...
}
A::A(const A& s){
// todo...
}
A& A::operator=(const A& s){
if(&s != this){
// todo...
}
return *this;
}
bool A::operator==(const A& s) const{
// todo...
return false;
}
bool A::operator!=(const A& s) const{
return !((*this)==s);
}
bool A::operator<(const A& s) const{
// todo...
return false;
}