类型显式转换
命名的强制类型转换:
cast-name<type>(expression);
其中 type 是要转换成的目标类型,expression 是要转换的值。如果 type 是引用类型,则结果是左值。cast-name 指定是哪种转换,有 static_cast, dynamic_cast, const_cast 和 reinterpret_cast。dynamic_cast 支持运行时类型识别。
static_cast
任何具有明确定义的类型转换,只要不包含底层 const,都可以使用 static_cast。如:
1 int j = 1, i = 2; 2 3 double cnt = static_cast<double>(j)/i; 4 5 cout << cnt << endl;//输出0.5
1 const char str[10] = "hello"; 2 const char *cp = str; 3 // char *q = static_cast<char*>(cp);//错误:static_cast 不能去掉底层 const 4 static_cast<string>(cp);//将字符面值转换成string类型,注意底层的const并没有去掉,即cp此时的类型是const string 5 // static_cast<const string>(cp);//和上一句效果一致 6 cout << cp << endl; 7 // cp += "world";//错误:const string 类型不能直接改变值
static_cast 对于把较大的算术类型赋值给较小的类型(编译器可能会发出警告,使用 static_cast 后能去除警告信息),以及对于编译器无法自动执行的类型转换非常有用。如:
1 double cnt = 1.23; 2 3 void *p = &cnt; 4 5 double *q = static_cast<double*>(p);//将p还原成于cnt对应的double*类型 6 7 cout << *q << endl;//输出1.23
在上面的代码中需要注意的是:当我们把指针存放在 void* 中,并且使用 static_cast 将其强制转换为原来的类型时,应该确保指针的值保持不变。即强制转换额结果将与原来的地址值相等。因此我们必须确保转换后所得的类型就是指针所指的类型。类型一旦不符,将产生未定义的后果。如:
1 int cnt = 1; 2 3 void *p = &cnt; 4 5 cout << p << endl; 6 7 double *q = static_cast<double*>(p);//将原来的int*转换成double*,*q将会是一个随机值 8 9 cout << q << endl; 10 11 cout << *q << endl;//在本次实验的pc上输出1.15686e-306
const_cast:
const_cast 只能改变底层const。如:
1 const char str[10] = "hello"; 2 const char *cp = str; 3 const_cast<char*>(cp);//const_cast能去掉底层const 4 cp = "hello world"; 5 cout << cp << endl;//输出hello world 6 const int cnt = 1; 7 // const_cast<int>(cnt);//错误,const_cast不能改变顶层const 8 int yy = 1; 9 // const_cast<double>(yy);//错误,const_cast只能去掉底层const而不能做其他类型转换
const_cast 常常用于有函数重载的上下文中。
reinterpret_cast:
reinterpret_cast 通常为运算对象的位模式提供较低层次上的重新解释。如:
int *ip;
char *pc = reinterpret_cast<char*>(ip);
我们必须牢记 pc 所指的真实对象是一个 int 而非字符,如果把 pc 当成一个普通的字符指针使用就可能在运行时发生错误。如:
string str(pc);
可能导致异常的运行时行为。
如上列子所时,使用 reintertpret_cast 是非常危险的,应该尽量避免使用。
强制类型转换干扰了正常的类型检查,很容易出错,应尽量避免使用。
旧式的强制类型转换:
type(expr);//函数形式的强制类型转换
(type) expr;//c语言风格的强制类型转换
根据所涉及的类型不同,旧式的强制类型转换分别具有与 const_cast, static_cast 或 reinterpret_cast 相似的行为。当我们在某处执行旧式强制类型转换时,如果换成 const_cast 和 static_cast 也合法,则其行为与对应的命名转换一致。如果换后不合法,则旧式强制类型转换执行与 reinterpret_cast 类似的功能:
int *ip;
char *pc = (char*) ip;
效果与使用 reinterpret_cast 一样。