Effective C++: Item01 ~ Item04
Item01:C++是一门多范式编程语言
-
面向过程 面向对象 泛型编程 STL
Item02:尽量以const、enum、inline替换#define
-
#define 是由预编译器处理的,所以定义的一些常量名不会出现在编译阶段的符号表里,这样在编译报错的时候,定位出错位置将耗费时间。 推荐:使用const常量替代#deifine定义常量。 当类的普通成员需要依赖于类的静态成员时,可以使用enum替代。 class GamePlayer { public: static int number; enum { NUM = 10 }; int scores[NUM]; // 这里的NUM不能使用static成员实现,因为类定义中静态成员只是声明,静态成员的实现是在类外部。 }; int GamePlayer::number = 10; #define经常被用来实现宏函数,但是因为它只是单纯的文本的替换,所以使用要十分小心。 推荐:使用inline替代宏函数。
Item03:尽可能使用const
-
const修饰指针变量时,在*左边表示指针所指的内容不可变,在右边表示指针自身不可变。 const可以修饰一个函数的返回值、参数、函数自身(成员函数)。 class Rational { ... }; const Rational operator* (const Rational &lhs, const Rational &rhs); // 返回const修饰的返回值,可以避免以下情况的发生: Rational a, b; (a * b) = c; // error, (a * b)的结果是const的 // 这有利于在条件判断中将==误写为=时及时发现错误 const成员函数和non-const成员函数可以构成重载,在对const对象调用函数时,调用const成员函数。 通过向成员变量添加mutable修饰符,使得const成员函数内部可以修改成员变量。 当const和non-const成员函数有着实质等价的实现时,令non-const调用const版本可以避免代码重复。
Item04:确定对象在使用之前已被初始化
-
在类的构造函数内完成所有成员(内置类型和自定义类型)的初始化(使用初始化列表,而不是在构造函数中赋值)。 注意区分初始化和赋值的区别。 基类的初始化总是优先于派生类的初始化,成员变量的初始化顺序与声明的顺序相同。 编译单元:产出单一目标文件的源码。 无法确定不同编译单元内non-local static对象的初始化顺序。 B b; // B是另一个文件中的全局变量(non-local static) class A { public: A() { b.init(); } // 这里在调用的时候,并不能保证b已经初始化了 }; 解决办法:通过定义一个函数将non-local static对象作为返回值返回。 B& getB() { static B b; return b; } // 在A中通过getB()就可以获得初始化后的对象。
