【Effective C++】读书笔记 Part5 实现
条款27:尽量少做转型动作
C++中的类型转换语法
类型转换语法主要有三种不同的形式:
- (T)expression //将expression转型为T
- T(expression) //将expression转型为T
两种形式除了写法不同之外,没有其他差别,都是C语法中的旧式转换(old-syle casts)。
- C++提供四种信使转换(new-style 或者 C++-sytle casts)
- const_cast( expression )
- dynamic_cast( expression )
- reinterpret_cast( expression )
- static_cast( expression )
各有不同的目的。
const_cast:通常用来将对象的常量性移除,也是唯一有能力的C++-style转型操作符。将const转为non-const。
dynamic_cast:主要用来“执行安全向下转型”,它用来决定某对象是否是继承体系中的某个类型。它是唯一一个无法由旧式转型语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
static_cast:编译器隐式执行的任何类型转换都可以由static_cast。只有当编译类型之间可以进行隐式转换,或者是类层次间的下行转换,static_cast的转换才是合法的,否则就会出错。如int向double的转换,double向int的转换, *向其他类型的指针的转换。pointer-to-base向pointer-to-derived的转换。
reinterpret_cast:主要是执行低级转换,实际动作可能取决于编译器,这就表示了它不可移植。主要是提供存储内容的比特位的重新解。
- 转型总会带来一些副作用,任何一个类型转换往往都令编译器编译出一些运行期间执行的代码。
- 在多重继承的时候,derived class的指针值和相应的base class的指针值是不同的。
- dyname_cast转型的执行速度往往非常慢。主要是将exppression转换为类的指针,引用void *类型。
dynamic_cast涉及运行时类型检查,dynamic运行时候类型检查需运行时类型信息,而这个信息存放在虚函数表中,只有定义了虚函数的类才会有虚函数表,所有对没有虚函数的类使用会导致编译错误。
如果编译通过,在运行时候,dynamic_cast都先会判断类型转换是否有效(可能需要多次class名称的strcmp,速度较慢),如果类型转换无效,就会将转换后的指针置为null,或者在转换为引用的时候抛出bad_cast异常。
最后:
- 如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_cast。
- 如果转型是必要的,试着将它隐藏在某个函数背后。客户可以直接调用该函数,而不需要将转型放进他们的代码中。
- 宁可使用C++style的新式转型,也不要使用旧式转型。前者很容易辨认出来,而且也有着比较分门别类的职责。