条款1:视C++为一个语言联邦
C++是由C、Obect-Oriented C++(C with class)、Template C++、STL组成的“语言联邦”。
条款2:尽量以const、enum、inline替换#define
-
- 由于宏定义是在预处理阶段处理的,只是进行简单的字符串替换,因此它不会检查语法,宏定义的类似变量的东西也不会进入记号表(symbol table),报错时不会提供错误准确位置信息。若使用非你所写的头文件,宏定义可能存在相同的风险。
解决方法:用const常量替换宏。
- 由于宏定义是在预处理阶段处理的,只是进行简单的字符串替换,因此它不会检查语法,宏定义的类似变量的东西也不会进入记号表(symbol table),报错时不会提供错误准确位置信息。若使用非你所写的头文件,宏定义可能存在相同的风险。
const double pai = 3.14
两种特殊情况:
(1)定义常量指针(所指为常量):const int *p或int const *p
。由于常量定义式通常被放在头文件内,因此有必要也将指针声明为const,即const char * const p = “abc”
;
(2)定义class专属常量:该常量作用域仅为类内,且为了确保常量只有一份,须在类内声明为static成员class ABC{static const int a;}
。最好确保同时在类外进行定义并初始化const int ABC::a = 5 ;
。#define不能创建一个class专属常量,它不重视作用域,同时也不能提供任何封装性。
-
- 枚举类型可等价于int使用,也可以当作类的专属静态整型变量。有的编译器不允许类内初始化静态成员变量,可在类内声明定义一个枚举类型对当作静态整型变量使用。此外,枚举类型不允许取地址。
-
- 形似函数的宏最好改用inline函数替换#define。
- 形似函数的宏最好改用inline函数替换#define。
条款3:尽可能使用const
-
- const出现在星号左边,表示被指物为常量;const出现在星号右边,表示指针为常量。给用户返回常量可降低客户造成的意外,又不至于放弃安全性和高效性。
-
- 两个成员函数如果只是常量性不同(this指针是否被声明为常量),其可以被重载。const成员函数可以接收非常量对象和常量对象,普通成员函数只能接收常量对象。
class ABC
{
const char& operator[]() const
}
-
- 若在const成员函数中想要修改某些成员变量,可将这些变量设为mutable。
-
- 当const和非const成员函数有着实质等价的实现时,令非const版本调用const版本可避免代码重复。也就是说,常量对象调用const成员函数,非常量对象调用非const成员函数的“壳子”,但实质仍是调用const成员函数。只不过进行了类型转换。下例进行了两次类型转换:第一次是对this指针添加const特性,第二次是对调用const成员函数后返回值进行移除了const。
- 当const和非const成员函数有着实质等价的实现时,令非const版本调用const版本可避免代码重复。也就是说,常量对象调用const成员函数,非常量对象调用非const成员函数的“壳子”,但实质仍是调用const成员函数。只不过进行了类型转换。下例进行了两次类型转换:第一次是对this指针添加const特性,第二次是对调用const成员函数后返回值进行移除了const。
条款4:确定对象被使用前已经初始化
-
- 对于内置类型对象(int,double…)进行手工初始化,因为C++不保证初始化它们。对于其他,初始化责任在构造函数。
-
- C++规定对象的成员变量初始化动作发生在进入构造函数之前。本质上先调用default构造函数对成员变量进行初始化,之后调用自定义的构造函数对成员变量进行重新赋值。
- C++规定对象的成员变量初始化动作发生在进入构造函数之前。本质上先调用default构造函数对成员变量进行初始化,之后调用自定义的构造函数对成员变量进行重新赋值。
-
- 代替构造函数赋值“假初始化”,用列表初始化效率更高,是真正的自定义的初始化。最好总是在初值列表中列出所有成员变量。初值列表列出的成员变量,其摆列次序应该和它们在class中声明次序相同。
- 代替构造函数赋值“假初始化”,用列表初始化效率更高,是真正的自定义的初始化。最好总是在初值列表中列出所有成员变量。初值列表列出的成员变量,其摆列次序应该和它们在class中声明次序相同。
-
- 如果成员变量是const或者引用,那么它们必须是被初始化而不是赋值!!!
-
- 当不同源文件中的static对象之间有先后次序依赖初始化时,需要确保在另一个文件中static对象被用于初始化本文件中的static对象之前进行初始化 。做法:将一个文件中的non-local static对象的初始化放入一个专属函数中,并返回初始化后的引用。若别的文件中要使用该对象,则先调用该对象的专属函数,从而必然导致在使用该对象前进行初始化,且返回引用不影响后续使用。如下例:
- 当不同源文件中的static对象之间有先后次序依赖初始化时,需要确保在另一个文件中static对象被用于初始化本文件中的static对象之前进行初始化 。做法:将一个文件中的non-local static对象的初始化放入一个专属函数中,并返回初始化后的引用。若别的文件中要使用该对象,则先调用该对象的专属函数,从而必然导致在使用该对象前进行初始化,且返回引用不影响后续使用。如下例: