Maple's Story

学习笔记:Effective C++ (二):构造析构赋值运算

字数统计: 648阅读时长: 2 min
2020/08/26 Share

05. 了解 C++ 默默编写并调用哪些函数

如果没有主动创建,编译器会在首次被调用时,为 class 创建默认构造函数、拷贝构造函数、拷贝赋值符( = ),以及析构函数。这些函数都是 publicinline 的。

除非这个 classbase class 自身有虚析构函数,否则编译器自动生成的是非虚析构函数。

对于 拷贝赋值符,如果 class 包含 const 成员 或者 reference 成员,以及 base class 中的拷贝赋值符为 private 时,编译器会拒绝自动生成赋值运算符。


06. 若不想使用编译器自动生成的函数,应明确拒绝

通过将相应的成员函数声明为 private 并且不进行实现,或者通过继承一个 Uncopyable 的类,可以阻止编译器自动生成。


07 为多态基类声明 virtual 析构函数

  • 带有多态性质的 base classes 应该声明一个 virtual 析构函数。如果函数带有任何 virtual 函数,他就应该拥有 virtual 析构函数。
  • 如果一个 class 的设计不是用于作为 base classes 使用的,就不该声明 virtual 析构函数。( 存在虚函数会需要生成虚函数指针和虚函数表,占用大量空间。)

08 别让异常逃离析构函数

  • 析构函数绝对不能抛出异常,如果一个析构函数调用的函数可能抛出异常,析构函数应该能捕捉任何异常,然后吞下它(不传播)或者结束程序。
  • 如果客户需要对某个操作函数运行期间抛出的异常作出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。

09 不在构造、析构过程中调用 virtual 函数

因为父类构造、析构函数运行时,子类并不存在,故此时调用 virtual 函数不会下降至子类中。


10 令 operator= 返回一个 reference to *this

为了实现「连锁赋值」


11 在 operator= 中处理 「自我赋值」

确保任何函数操作一个以上对象,而其中多个对象为同一对象时,行为仍然正确。


12 复制对象时勿忘其每一个成分

  • Copy 函数应该确保复制「对象内的所有成员遍历」 以及「所有 base class 成员」。
  • 不要尝试以某一个 coping 函数实现另一个 coping 函数。应该把相同的代码部分放在第三个函数中,并由两个 coping 函数共同调用。
CATALOG
  1. 1. 05. 了解 C++ 默默编写并调用哪些函数
  2. 2. 06. 若不想使用编译器自动生成的函数,应明确拒绝
  3. 3. 07 为多态基类声明 virtual 析构函数
  4. 4. 08 别让异常逃离析构函数
  5. 5. 09 不在构造、析构过程中调用 virtual 函数
  6. 6. 10 令 operator= 返回一个 reference to *this
  7. 7. 11 在 operator= 中处理 「自我赋值」
  8. 8. 12 复制对象时勿忘其每一个成分