static_cast
任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast,例如将一个整形的运算对象强制转换为doule类型。static_cast常见的用法有以下两种:
- 类型之间的转换,例如 doule 转为 int.
可以用于编译器无法自动执行的类型转换也非常有用,可以使用static_cast找回存在于void* 指针中的值,例如
void p =&d;
double dp = static_cast(p);
当我们把指针保存在void当中,并且使用static_cast找回转换的值得时候,应该保证void 指针的值不变,如果一旦类型发生了变换,那么将产生未定义的后果。
static_cast作类型转换的时候需要我们自己去确保转换的类型是匹配的,static_cast可以用在指针和引用上,还可以用在基础数据和对象上,用static_cast来处理的转换就需要两者具有”一定的关系”了,实际上继承关系是可以被static_cast接受的,其他情况的指针和引用转换都会被static_cast直接扔出编译错误,而这层关系上的转换又几乎都可以被dynamic_cast所代替
const_cast
const_cast 只能改变运算对象底层的const修饰、
对于将常量对象转为非常量对象的行为,我们一般称之为去掉const性质,一旦我们去掉了某个对象的const性质,编译器就不在阻止我们对该对象进行修改了,虽然我们可以获取修改对象的权限,但是这样的操作时未定义的。阅读
reinterpret_cast
reinterpret_cast运算符用来处理无关类型之间的转换,他会产生一个新值,这个值会与原始参数有完全相同的bit位。
IBM的C++指南里倒是明确告诉了我们reinterpret_cast可以,或者说应该在什么地方用来作为转换运算符:
- 从指针类型到一个足够大的整数类型
- 从整数类型或者枚举类型到指针类型
- 从一个指向函数的指针到另一个不同类型的指向函数的指针
- 从一个指向对象的指针到另一个不同类型的指向对象的指针
- 从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
- 从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针
dynamic_cast
与static_cast一样,dynamic_cast的转换也需要目标类型和源对象有一定的关系:继承关系。 更准确的说,dynamic_cast是用来检查两者是否有继承关系。因此该运算符实际上只接受基于类对象的指针和引用的类转换。
对于从子类到基类的指针转换,static_cast和dynamic_cast都是成功并且正确的(所谓成功是说转换没有编译错误或者运行异常;所谓正确是指方法的调用和数据的访问输出是期望的结果),这是面向对象多态性的完美体现。
而从基类到子类的转换,static_cast和dynamic_cast都是成功的,但是正确性方面,我对两者的结果都先进行了是否非空的判别:dynamic_cast的结果显示是空指针,而static_cast则是非空指针。但很显然,static_cast的结果应该算是错误的。
如果基类或者子类没有任何虚函数(如果基类有虚函数表,子类当然是自动继承了该表),当他们作为dynamic_cast的源类型进行转换时,编译也会失败。
这种情况是有可能存在的,因为在设计的时候,我们可能不需要让子类重写任何基类的方法。但实际上,这是不合理的,
如果要用继承,那么一定要让析构函数是虚函数;如果一个函数是虚函数,那么在子类中也要是虚函数。