条款01:视C++为一个语言联邦
C++最开始就是c加上一些面向对象的特性。随着其发展,它加入了template模板以支持泛型,STL标准模板库以扩张其功能。
如今C++已经是一个多重泛型的编程语言,同时支持过程形式、面向对象形式、函数形式、泛型形式、元编程形式的语言。
为了理解C++,可将其分为4个主要特性:
- C。C++很多内容不过是较高级的C解法。包括区块、语句、预处理器、内置数据类型、数组、指针等内容都是来自于C。
- Object-Oriented C++。这部分就是面向对象说展示出来的类、封装、继承、多态、virtual函数等方面的内容。
- Template C++。即C++的泛型编程部分。
- STL。STL是C++中的template程序库,也称为标准模板库,对于容器、迭代器、算法及函数对象都有很好的规约协调。
条款02:尽量以const,enum,inline代替#define
用一句话来概括这个标题就是“用编译器来替换预处理器做的工作”。
使用#define可能会导致符号未进入源码中的记号表,如#define PI 3.14,预处理后代码中不含PI符号,全部被替换为3.14,导致调试的困难,使用const可以避免这种情况。
在一个class里面,无法利用#define创建一个类成员,因为#define不重视作用域(scope),一旦产生宏定义,它在后面的过程中都是有效的,除非进行#undef,这意味着#define不但提供类成员定义的功能,也不能够提供任何封装性。但是可以通过const来实现。
如果不希望别人通过pointer和reference来指向你的常量,可以用enum来实现这个约束。它和#define一样不会导致非必要的内存分配。
对于使用宏定义的函数,使用#define定义可能导致导致多次自增问题,为形参提供括号等多个方面的细节必须被考虑到,而且它不会进行类型检测,使用inline函数可以完美的解决这个问题。inline提供了宏定义的效率和类型安全性。
条款03:尽可能使用const
const可以修饰一个常量指针const int *p,标识指针指向的对象是常量不能改变;也可以修饰指针常量int *const p,表示指针是一个常量,它只能指向该对象。
const最具威力的应用是在面向函数时的应用,可以修饰返回值、各个参数、函数自身等。
const成员函数,即在函数名后加上const的形式,表示在函数内不能对成员变量进行任何修改,更严格的限制可以理解为也不能通过函数的范围值对成员变量进行修改,如等号的重载函数。要解决这个问题可以用mutable来修改成员变量,表示其是可以在const成员函数中对其进行修改。
为了对一个const成员进行更改,可以使用const_cast<>来进行类型转换。
当一个成员函数同时有着const和non-const实现时,可以考虑直接在其non-const版本类调用经过const_cast<>转换的const成员函数版本,以避免代码重复。
条款04:确定对象在使用前已经先被初始化
读取为初始化的值将导致不明确的行为。
对象的成员变量的初始化动作在进入构造函数之前进行,这意味着不能够在构造函数内对于const成员变量记进行赋值。可以使用初始化列表来实现对于const成员变量的初始化,让初始化和赋值动作同时完成。
class内的成员变量总是以其声明次序被初始化,基类对象先于派生类对象进行构造动作,派生类对象先被析构,基类对象后被析构。
static对象其生命周期从其声明直到程序运行结束,包括local-static对象和non-local static对象,递归函数内的static成员就是在有在第一次声明时才分配内存并初始化,其后都会忽略该语句。
将local static对象替换为non-local static对象可以确保其初始化次序,在类中被初始化。
增加一点:static关键字的作用1)将全局变量、函数声明为static类型可以让它在其他cpp的作用域中被隐藏。2)保持变量内容的持久,可以到程序结束时其生命周期才结束。3)默认初始化为零。