💻 C++ | 类设计者的核查表

(来自《C++沉思录》)
C++ 提供了强大的类,使得我们能够以更加优雅的方式写代码。而设计一个类的时候,初学者往往会忘记一些东西而导致 BUG 源源不断(比如我),所以,初学者就需要一个核查表来时刻提醒自己。他不是任务清单,但是他可以帮助你回忆起可能会忘记的事前。

你的类需要一个构造函数吗?

  • 如果是一个比较复杂的类,那么就需要构造函数来隐藏它们内部工作方式。

你的数据成员是私有的吗?

  • 私有的数据成员能够帮助我们更好地维护类里面的数据,有一个统一的管理可能会减少 BUG 的发生。

你的类需要一个无参的构造函数吗?

  • 如果你想声明该类的对象可以不显式地初始化他们,那么就必须显式地写一个无参的构造函数,否则
  • 1
    2
    Point p;	//错误,没有初始化
    Point pa[1000]; //错误

是不是每个构造函数初始化所有的数据成员?

  • 如果某些数据成员没有显式地初始化,那么,他们的行为将不可预料。比如你的类里面有一个指针 p,如果你没有显式地初始化,那么他将会是一个不可预料的值,而 p == NULL 这个语句就没有意义了。因为他一开始可能并不是 NULL。

类需要析构函数吗?

  • 并不是所有的类都需要析构函数,但是如果你用了 new 的话,通常析构函数需要包含 delete。

类需要一个虚析构函数吗?

  • 不用做基类的类是不需要虚析构函数的,虚函数只有在继承的时候才能发挥作用。而虚析构函数通常是空的。

  • 1
    2
    B* bp = new D;   //假设B是D的基类
    delete bp; //这里就出现问题了,如果B没有虚析构函数,那么他将调用错误的析构函数。

你的类需要复制构造函数吗?

  • 如果你的类里面存在着通过 new 生成的数据,那么如果没有复制构造函数的话,复制类的对象就会复制指针,使得两个类中的数据成员指向同一个地方,那么当这两个对象要被销毁的时候,这个内存就会被释放两次,就会出现 BUG。

  • 如果不想用户复制类的对象,那么就要把复制构造函数私有化。

你的类需要一个赋值操作符吗?

  • 理由和上面一样,通常 operator=的返回值是一个 X&, 通常是 *this,保证内建的复制操作符一致。

你的赋值操作符能正确地将对象赋给对象本身吗?

  • 通常我们赋值的时候会用到“先释放旧值,再复制”的原则,但是当复制的对象是本身的时候,那就有可能在还没有复制之前就把对象给销毁了。

  • 避免这个问题的最简单的方法就是显式地加以预防。

    1
    2
    3
    if(&s != this){
    ...
    }
  • 又或者先把旧的值保存起来然后知道复制完成。

你的类需要定义关系操作符吗?

  • 如果你想创建类型的有序集合或者比较相等的话,那么就需要关系操作符了。

删除数组时你记住了用 delete[]吗?

  • 如果 new 用到了[]那么删除的时候也需要用到[]

记得在赋值构造函数和赋值操作符的参数类型中加上 const 了吗?

  • 如果没有加上 const 那么可能在复制的时候调用了默认隐式的函数。

如果函数有引用参数,它们应该是 const 引用吗?

  • 对于不允许改变的值,最好加上 const,预防 bug 的出现。

记得适当地声明成员函数为 const 的了吗?

  • 理由同上
  • 对于一些 const 的参数,只能调用 const 的函数,如果不声明为 const 的话,那么将无法调用(静态函数同理)

以上就是对 C++类的一些经常需要注意的问题的总结

土豪通道
0%