C++中常见类型转换方法:static_cast
、dynamic_cast
、const_cast
、reinterpret_cast
。
使用形式为cast-name<type>(expression)
1. static_cast
:
任何具有明确定义的类型转换,只要不包含底层const
,都可以使用static_cast
。
#include <iostream>
int main()
{
int a = 12;
int b = 24;
float c = static_cast<float>(a) / static_cast<float>(b);
std::cout << "c: " << c << std::endl; // 输出0.5
}
static_cast
对于编译器无法自动执行的类型转换也非常有用,例如:
#include <iostream>
int main()
{
double d = 9.;
void *p = &d;
double *pd = static_cast<double*> (p);
std::cout << "*pd: " << *pd << std::endl; // 输出9
}
2. const_cast
:
对于const_cast<type>(expression)
来说type
必须是指针、引用或指向对象类型成员的指针。
唯有 const_cast
可用于转型掉(移除)常性或易变性。只有const_cast
能改变表达式的常量属性,使用其它形式的命名强制转换改变表达式的常量属性都将引发编译器错误。
对于将常量对象转换成非常量对象的行为,一般称其为“去掉const性质(cast away the const)”,一旦去掉了const性质,编译器就不再阻止我们对该对象进行写操作了。
#include <iostream>
#include <string>
int main()
{
const char *pc = "const_cast example.";
/* 字符串字面值转换为std::string类型 */
std::string pcstr = static_cast<std::string>(pc);
/* 改变对象的底层const */
char *pcc = const_cast<char*>(pc);
/* 下面两句输出相同,都是const_cast example. */
std::cout << pcstr << std::endl;
std::cout << pcc << std::endl;
}
图1 正确使用const_cast
《C++ Primer中文版》(第5版)中所述下面规则在Visual Studio 2013和Visual Studio 2017上编译器上不适用(其它编译器未测试):
如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为,但是如果对象是一个常量,再使用const_cast执行写操作就会产生未定义行为。
#include <iostream>
int main()
{
int a = 9;
int *b = const_cast<int *>(&a);
*b = 8;
std::cout << "a: " << a << std::endl; // 8
std::cout << "*b: " << *b << std::endl; // 8
int i = 3;
const int& rci = i;
const_cast<int&>(rci) = 4;
std::cout << "i = " << i << '\n'; // 4
std::cout << "rci = " << rci << '\n'; // 4
const int j = 3;
int* pj = const_cast<int*>(&j);
*pj = 4;
std::cout << "j = " << j << '\n'; // 3
std::cout << "*pj= " << *pj << '\n'; // 4
}
3. reinterpret_cast
:
reinterpret_cast
通常为运算对象的位模式提供较低层次上的重新解释。
#include <iostream>
#include <string>
int main()
{
int *pi = new int;
*pi = 90;
char *pc = reinterpret_cast<char*>(pi);
std::string str = std::string(pc);
std::cout << *pi << std::endl; // 90
std::cout << *pc << std::endl; // Z
std::cout << str << std::endl; // Z
delete pi;
}
图2 reinterpret_cast