- 大多数情况下,提出class定义以及function声明,是花费心力较多的事儿。
-
条款26:尽量延后变量定义式的时间
- 在程序到达定义变量式的地方,以及离开作用域,会承担变量的构造和析构成本。如果这个变量没有被用到,则会浪费这些成本,所以变量的定义尽量延后。
- 变量未被用到,可能因为在前面有return,或者抛出异常。
- 变量的定义最好在需要他的地方。
- 变量定义最好能够直接初始化,而不是定义后再赋值。
- 如果是在循环中使用到变量,是在循环外定义变量,然后每次循环赋值;还是在循环内每次初始化变量?那么要考虑是一次赋值操作效率高,还是一次构造+析构效率高。
-
条款27:尽量少做转型动作
-
转型(casts)破坏了“类型系统”,可能导致一些麻烦,有些容易看出,有些则比较隐晦。
-
两种旧式转型类似这样:
(T) expression T (expression)
-
C++还提供了四种新式转型(C++-style casts):
const_cast<T>(expression) dynamic_cast<T>(expression) static_cast<T>(expression) reinterpret_cast<T>(expression)
-
const_cast通常用来将对象的常量性转除。它也是唯一 有此能力的C++-style转型操作符。
-
dynamic_cast主要用来执行 ”安全向下转型 “,也就是用来决定某对象是否归属继承体系中的某个类型。
-
static_cast用来执行强迫隐式转换,例如:将一个 non-const 对象转换为 const 对象,或将一个 int 转为 double等等。它也可以用来执行上述多种转换的反向转换,例如:将 void* 指针转为 typed 指针,将 pointer-to-base 转为 pointer-t0-derived。但它无法将 const 转为 non-const,这个只有 const_cast才办得到。
-
reinterpret_cast执行低级转型,实际动作(及结果)可能取决于编译器,这也就表示它不可移植。 例如:将一个 pointer to int 转型为 int。
-
类型转换不只是将一个东西看做另一个类型,任何一个类型转换往往真的令编译器编译出运行期间执行的码。
比如int转为double,他们的底层表示肯定不一样。
再比如一个基类指针指向一个派生类对象,他们的地址可能都不一样,说明单一对象(例如一个类型为Derived的对象)可能拥有一个以上的地址(比如 以"Base* 指向 " 和 以" Derived* 指向" 时的地址)。这在C++的多重继承中是有可能出现的,所以不能编写代码时假设变量的布局等。
-
另一个问题,许多设计要求派生类内的虚函数的第一个动作是调用基类的对应函数。
假设我们有个 Window 的base-class 和一个 SpecialWindow的derived-class,两者都定义了 virtual函数onResize。SpecialWindow 的 onResize 函数被要求收先调用Window的onResize。这怎么实现呢?假如我们用转型:
class Window { // 基类 public: virtual void onResize() { ... } ...</
-