红联Linux门户
Linux帮助

编写C++类的条款

发布时间:2015-04-12 16:34:21来源:linux网站作者:leby

如何专业的定义一个class?这里记录一下自己的checklist

关于构造函数的注意点

a. 构造函数声明为explicit,避免隐式转换

b. 考虑禁用复制构造函数、赋值函数

c++中,默认对于类会产生以下成员函数(如果你没有定义的话,这通常是不可控的)
 
class Empty() {
public:
Empty();
~Emtpy();                                  
Empty* operator&();                  //取址运算符
const Empty* operator&() const;      //取址运算符 const
private: 
Empty(const Empty &);                //赋值构造函数
Empty& operator=(const Empty &);     //赋值运算符
}

这里取址函数不用多说,关键是赋值相关的两个函数,默认是浅copy的,所以还是禁用,参考析构函数注意点

c. 构造函数尽管可以抛出异常,但没有返回值;所以可以考虑单独实现一个Init函数作为补充

采用初始化列表而不是赋值初始化成员变量,有两种情况你必须这样做:

a. const \ reference的成员

b.派生类的方法中需要调用基类的构造函数

Base(int x):m_x(x) {
}

Derived(int x) : Base(x) {
}

成员函数如果不改变类的状态,声明时后加const

尽可能将成员变量private更可控,更透明

以非member 方法代替需要多个对象的member组合功能的实现

考虑Law of Demeter,适当做一个权衡,少一些wrapper或中介类

关于析构函数的注意点
a. 一个类要被继承时(其往往含有虚函数要多态),要提供虚析构函数,否则存在下面的情况:

Base *pb = new Derived();
delete pb;//这里就不会调用派生类的析构函数,尽管pb的虚指针指向了派生的虚表,但其虚表中没有虚析构函数,造成派生对象资源泄露

b.只要有基类的析构函数是虚拟的,那么所有的派生类不管是否明确的写了虚拟析构函数,派生了的析构函数可以认为一定是虚拟的。如同类的虚指针,所有派生的默认都有

c.在析构中不要抛出exception,否则实现此异常接口
如果类含有指针成员和引用成员,则该类型通常需要实现析构函数(这里不一定是虚的,但是需要考虑清理内存)
更进一步,一旦实现了析构函数,就进而需要实现实现拷贝构造函数与拷贝复制函数,否则,需要明确拒绝(或者,仅仅一个理由:做副本有没有道理,见这里第一个条款)