Effective C++改善程序与设计的55个具体做法(第三版)
1、 让自己习惯C++
条例01.:视C++为一个语言联邦
1、 C,C++的基础。局限:没有模板(template)、没有异常(exceptions)、没有重载…
2、 Objective-Oriented C++。封装、继承、多态、虚函数。
3、 Template C++。其中MTP,模板元编程。
4、 STL。容器、迭代器、算法、函数对象。
条款02:尽量使用const、enum、inline替代#define
1、 enum{NumTurn = 5}。如果不想别人获得一个指针或引用指向你的某个整数常量,enum可以帮助实现这个约束。
2、 对于单纯常量,最好以const对象或enums替代#define
3、 对于函数的宏,最好改用inline函数替代#define
4、 class中的static const 常数成员,类内声明,类外定义。
5、 预处理器中,#include仍然是必需品,#ifdef/#ifndef也继续扮演控制编译的重要角色。
#ifndef可以防止重复定义。
条款03:尽可能使用const
1、 const出现在星号(*)左边,表示所指物是常量;const出现在星号右边,表示指针本身为常量。Const_iterator 所指物不可变。
2、 将const实施于成员函数的目的,是为了确定该成员函数可作用于const对象身上。Const对象只能调用const成员函数。
3、 关键字Mutable可用于修饰成员变量,使成员在const成员函数中可变。
4、 在重载的const和non-const成员函数中,可以在non-const成员函数中调用const版本,避免代码重复。
条款04:确定对象被使用前已先被初始化
1、 C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。
2、 Static变量(全局和局部)在main函数结束时才调用其析构函数。
3、 为免除“跨编译单元之初始化次序”问题,请以local static对象替代non-local static对象。也就是把non-local static 放入到函数内,使函数返回指向这个local static的引用。这个手法(Singleton)的基础在于:c++保证,函数内的local static对象会在“该函数被调用期间”“首次遇上该对象之定义式”时被初始化。
2、 构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数
1、 默认构造函数、复制构造函数、赋值操作符、析构函数(非virtual)。
2、 C++不允许“让reference改指向不同对象”。
3、 如果某个base classes将copy assignment声明为private,编译器将拒绝为其derived classes生成copy assignment操作符。
条款06:若不想使用编译器自动生成的函数,就该明确拒绝。
1、 为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。使用像Uncopyable这样的base class也是一种做法。
条款07:为多态基类声明virtual析构函数。
1、 C++明白指出,当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义----实际执行时通常发生的是对象的derived成分没被销毁。
2、 析构函数被定义为pure virtual函数时,需要为这个pure virtual析构函数提供一份定义。
3、 构造函数,先构造基类;析构函数,先析构派生类。
4、 带多态性质的基类应该声明一个virtual析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。
条款08:别让异常逃离析构函数
1、 析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。
2、 如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非析构函数中)执行该操作(以防万一)。
条款09:绝不在构造和析构过程中调用virtual函数
1、 因为无法使用virtual函数从base class向下调用,在构造期间,可以借助“令derived classes 将必要的构造信息向上传递至base class构造函数”。
条款10:令operator=返回一个reference to *this
1、 为了实现“连锁”赋值“,赋值操作符必须返回一个reference指向操作符的左侧实参。
条款11:在operator=中处理“自我赋值“
1、 可以使用“证同测试“(if判断)达到自我复制的目的,但是不具备异常安全。
2、 可以精心周到的对语句手工排序(先保存旧值)、以及copy-and-swap达到异常安全。
条款12:复制对象时勿忘其每一个成分
1、 当你编写一个copying函数,请确保(1)复制所有local成员变量,(2)调用所有base classes内的适当的copying函数(初始化列表中)。
2、 不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放进第三个函数(一般private)中,并由两个copying函数共同调用。