1、static_cast
任何只要具有明确定义的类型转换,只要不包含底层const就可以使用static_cast
当需要把一个较大的算数类型赋值给一个较小的算数类型,static_cast非常有用。
此时,强制类型转换告诉程序的读者和编译器:我们不在乎潜在的精度损失。一般来说,如果编译器发现一个较大算数类型试图赋值给一个较小的类型,会给出警告信息,但是我们执行了显式的类型转换后警告信息就会关闭。
static_cast对于编译器无法自动执行的类型转换也非常有用。例如我们可以通过static_cast找回存在于void
*指针中的值。
void *p = &a; //正确,任何非常量对象的地址都可以存入void*
double *ap = static_cast<double*>(p)
2、const_cast
const_cast只能改变运算对象的底层const_cast.
只有const_cast能改变表达式的常量属性,使用其他形式的强制类型转换改变表达式常量属性将引发编译器错误,同样的,不能用const_cast改变表达式的类型。
const char *cp;
char *q = static_cast<char *>(cp); //错误,static_cast不能去const属性
static_cast<string>(cp); //正确
const_cast<string>(cp); //错误,const_cast只能改变常量属性
3、reinterpret_cast
reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释。
例如:
int *ip;
char *pc = reinterpret_cast<char *>(ip);
我们必须牢记pc所指向的真实对象是一个int而非字符,如果把pc当做普通的字符指针使用就可能在运行时发生错误。例如
string str(pc);
可能导致异常的运行时行为。
使用interpret_cast是非常危险的,转换过程编译器不会给出人警告,因为是显示的强制类型转换。
4、dynamic_cast
dynamic_cast运算符用于将基类的指针或引用安全的转换成派生类的指针或引用。
使用形式如下:
dynamic_cast<type*>(e); //type必须是一个类类型,e必须是一个有效的指针
dynamic_cast<type&>(e); //e必须是一个左值
dynamic_cast<type&&>(e); //e不能是左值
1)指针类型的dynamic_cast
假设base类至少含有一个虚函数,Drived是base的共有派生。如果有一个指向Base的指针bp,则我们可以运行时将它转换成指向Drived的指针。如下:
运行时,如果bp指向Derived对象,则转换成功,if语句内的代码执行是安全的。
否则,转换结果为0,执行else语句内。
原因在于实际传入的参数对象可以是Base也可以是Derived,这是由于动态绑定造成的。
2)引用类型的dynamic_cast
引用类型的dynamic_cast和指针类型的在表示错误发生的方式上有所不同,因为不存在所谓的空引用。
当对引用类型转换失败时,程序抛出一个std::bad_cast异常,该异常定义在typeinfo头文件中。