这是Effective C++中第27个原则,作者花了很长的篇幅来介绍这一原则。
总而言之一句话,因为类型转换会导致破坏类型系统,从而带来明显的和不明显麻烦,而且这是C++独有的特性。
C++提供了四种新型的类型转换,就是下面这四种:
const_cast是把const类型转换成非const类型;
dynamic_cast是类体系中进行转换;
reinterpret_cast是一个很强大的类型转换,最常用的是指针转换为指针,而且是两个毫不相关的指针之间的转换,它传递的是比特位。换句话说这些比特位是不变的,但是它能按照另一种方式来解释它。
static_cast就是平常的类型转换,用的最广泛。
须知,在C++中,类型转换往往能够令编译器编译出运行时代码,可想而知,这个代码并不是你写的。在这里作者举了一个多态的例子,当你用父类的指针指向子类的对象时,父类的指针指向的地址和子类对象所在的地址并不是一个,它俩之间有时候是有个偏移量的。
作者又举了一个例子。现有一父类和其子类,两类有两个同名的虚函数,现要求子类虚函数中首先调用父类虚函数,这是子类虚函数的代码是这样子的。
通过子类的this指针强制类型转换成父类类型,然后调用同名函数。但是次转换的过程并不是你所想象的那样简单,这个强制类型转换会创造出一个被转型对象的副本,它是在这个副本身上执行父类的同名函数,而在该对象身上执行本类专属的同名函数,两者本应作用于同一个对象而实际上却没有。而解决这个问题的办法就是不用强制类型转换,你该用父类的成员函数就用就行了。
而dynamic_cast这个转换你最好不要用,因为它是动态转换,它会在整个类层次上进行寻找,而且每转换一次就寻找一次,并且它是按照类名进行字符串匹配的。
通常你使用dynamic_cast进行强制类型转换的情景是用一个父类的指针指向子类对象,这种情况你应该使用的是子类类型的只能指针,作者使用的是一个装有智能指针的vector。如果子类很多,并且你非要用父类类型的话,那你可以在父类中提供一个同名空虚函数,并在各个子类中去实现它,然后你再用vector去容纳装有父类类型的智能指针,然后去操作。为啥要使用vector呢?因为它是类型安全容器。
在这里一定要记住不要在程序中多次使用dynamic_cast做没有必要的类型转换,因为这样做不仅代码多,而且运行慢,因为dynamic_cast需要查找嘛。
最后作者衷心地告诉大家尽量不要使用强制类型转换,尤其是除static_cast之外的另外三种;强制类型转换如果必要,那也要把它包裹在一个函数里面,不要让用户接触到;推荐使用C++强制类型转换,它不仅容易分辨,而且各司其职。