目录
条款01 视C++为一个语言联邦(C++由几部分组成)
条款02 尽量以 const,enum,inline 替换 #define
条款03 尽量使用 const
条款04 确定对象再使用前已经被初始化
条款05 了解c++默默编写并调用那些函数
条款06 若不想使用编译器自动生成的函数就该明确拒绝
条款07 为多态基类声明 virtual 析构函数
条款08 别让异常逃离析构函数
条款09 绝对不在构造和析构函数中调用virtual函数
条款01 视C++为一个语言联邦(C++由几部分组成)
1. C语言:如内置数据类型,数组,指针等。
2. Object-Oriented C++(面向对象C++):如 class,封装,继承,多态,动态绑定等。
3. 泛型编程。
4. STL。
条款02 尽量以 const,enum,inline 替换 #define
1. 宏定义在编译预处理时被替换,故不方便调试。
2. 宏定义可能导致代码膨胀。
3. 一般宏定义无法限制作用域。
4. 宏函数是直接的代码替换可能带来未预料的问题如:
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b)) int a = 5,b = 0; CALL_WITH_MAX(++a,b);//a被累加两次 CALL_WITH_MAX(++a,b+10);//a被累加一次
条款03 尽量使用 const
1. 使用
const
可以清楚地表明某个变量、参数或返回值不应该被修改。这有助于其他开发者理解代码的意图,避免无意的修改。2.
const
关键字提供了一种在编译时捕捉错误的方式。如果尝试修改一个const
对象,编译器将报错,这有助于早期发现潜在的逻辑错误。
条款04 确定对象再使用前已经被初始化
说明:如果你使用了一个未被初始化的对象,可能会导致未定义的行为。(某些情况下c++会自动调用默认构造,但不是所有情况都会这样)
聊聊初始化列表:
搞清楚什么是赋值,什么是初始化。
在构造函数体内的赋值并非初始化。类的成员变量一般会先调用默认构造函数才会进入类的构造函数本体。相当于成员变量先调用了一次默认构造,又调了一次赋值构造。而初始化列表的调用时机早于构造函数体执行,相当于直接调用了成员对应的构造函数。
结论:推荐使用初始化列表来初始化成员变量。
条款05 了解c++默默编写并调用那些函数
书中强调类中的默认构造,默认拷贝构造,默认拷贝赋值,默认析构函数(实际不止这些)
条款06 若不想使用编译器自动生成的函数就该明确拒绝
说明:比如当我们希望某个对象是独一无二不能被拷贝时我们应该拒绝使用默认构造函数,
c++提供delete关键字来帮助我们做到这一点。
条款07 为多态基类声明 virtual 析构函数
基类没有为析构函数加virtual关键字,在使用多态特性时,如果我们 delete 了基类指针,通常派生类部分的资源不会被释放。
条款08 别让异常逃离析构函数
1. 析构函数绝对不要吐出任何异常,如果一个被析构函数调用的函数可能会抛出异常,析构函数因该捕捉任何异常,然后吞下他们或结束程序。
2.如果用户需要对某个函数运行期间抛出异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。
条款09 绝对不在构造和析构函数中调用virtual函数
在构造函数和析构函数中调用virtual函数往往不会走派生类的函数体。
因为在派生类构造时一些资源还没初始化,c++不允许这时候调用virtual函数以免发生未预料的事情,同理析构函数中可能有些资源已经被释放了。