C++中有五种强制类型转换
- static_cast
- const_cast
- reinterpret_cast
- dynamic_cast
- 旧式(C风格)强制类型装换
下面一一介绍
static_cast
只要不包含底层const,都可以使用
/*
static_cast<type>(exp) 将exp的结果转化为type类型
*/
double d = 10;
void *vp = &d;
double *dp = static_cast<double*>(vp);
cout << *dp << endl;
如果转换的类型不符,将会产生UB,且没有编译错误
const_cast
只能用于改变(添加或去掉)运算对象的底层const
//添加一个底层const
int val=10,*p=&val;
const int *cp = const_cast<const int*>(p);
//cp是底层const指针(即使不这么写,也会完成隐式转换)
const_cast的实际用途其实 在于去掉一个底层const
会有这样一种情况,本来不具有底层const的指针或引用,在传值的过程中被隐身转换为底层const,这时可以用const_cast去掉底层const
int val = 10;
const int *cp = &val; //cp虽然有底层const,但它所指的不是常量
int *pp = const_cast<int*>(cp); //去掉底层const后,可以通过pp改变val的值
/*一个错误的例子*/
const int cval = 10; //cp所指的cval本就是不许改变的常量
const int *cp = &cval;
int *pp = const_cast<int>(cp); //即使去掉了底层cosnt,通过pp对cval改值是UB
reinterpret_cast
reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释。举个例子,假设有如下的转换:
int *ip;
char *pc = reinterpret_cast<char*>(ip);
我们必须牢记pc所指的真实对象是int而非字符,如果把pc当成一个普通的字符指针使用就可能在运行时发生错误。例如:
string str(po);
可能导致异常的运行时行为。
使用reinterpret_cast是非常危险的,用pc初始化的例子很好地证明了这一点。其中的关键问题是类型改变了,但编译器没有给出任何警告或者错误的提示信息。当我们用一个int的地址初始化pc时,由于显式地声称这种转换合法,所以编译器不会发出任何警告或错误信息。接下来再使用pc时就会认定它的值是char*类型,编译器没法知道它实际存放的是指向int的指针。
dynamic_cast
只用于对象的指针和引用.
当用于多态类型时,它允许任意的隐式类型转换以及相 反过程.
不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast 会检查操作是否有效. 也就是说, 它会检查转换是否会返回一个被请求的有效的完整对象。检测在运行时进行. 如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL. 对于引用 类型,会抛出bad_cast异常 .
旧风格强制类型转换
type(expr) //函数形式的强制类型转换
(type)expr //C语言风格的强制类型转换
旧式的强制类型转换从表现形式上来说不那么清晰,容易看漏,而且一旦转换出现问题,追踪起来也很困难。