Maple's Story

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

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

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

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

除非这个 class 的 base 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 复制对象时勿忘其每一个成分