C++:强制类型转换

C++:强制类型转换

C中类型转换

1
2
3
4
5
double x = 2.333;
int y = (int)x;
int z = int(x);

char* a=(char*)malloc(sizeof(char)*8);

旧式类型转换不明了,查找错误较为困难,C++中建议使用C++风格的类型转换

cast-name<type>(expression)

static_cast

任何具有明确定义的类型转换,只要不包含底层const都可以使用

1
2
3
4
double slope = static_cat<double>(j)/i;

void* p=&d;
double *dp=static_cast<double*> p;

const_cast

只能改变运算对象的底层const

1
2
3
4
5
6
7
8
9
const char *pc;
char *p=const_cast<char*>(pc);
//正确,但是通过p写值为未定义的行为
char *q=static_cast<char*>(pc);
//错误,static_cast不能转换掉const的性质
static_cast<string>(pc);
//正确:字符串字面值转换为string类型
const_cast<string>(pc);
//错误,const_cast只能改变常量属性

使用例子:

1
2
3
4
5
6
7
8
9
10
const string &shorterString(const string&s1,const string &s2)
{
return s1.size()<=s2.size()?s1:s2;
}

string &shorterString(string &s1,string &s2)
{
auto &r=shorterSting(const_cast<const string&>(s1),const_cast<const string&>(s2));
return const_cast<string&>(r);
}

reinterpret_cast

通常为计算对象的位模式提供较低层次上的重新解释

1
2
3
4
int *ip;
char *pc=reinterpret_cast<char*>(ip);

string str(pc);//可能导致运行异常

reinterpret_cast依赖于机器,应谨慎使用

dynamic_cast

用于将基类指针或者引用安全地转换成派生类指针或引用

指针类型的dynamic_cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//假设一个Base基类,至少包含一个虚函数
classs Base{
public:
vitual sleep();
}
//假设存在一个Base的共有派生类
class Derived:public Base{
public:
sleep();
}

//要把一个Base指针转换为指向Derived的指针
Base* bp;
if(Derived *dp=dynamic_cast<Derived>(bp))
{//转换正确
//使bp指向Derived指针
}else{//转换错误
//是bp指向Base*指针
}

在条件部分执行dynamic_cast操作可以确保类型转换和结果检查在同一条表达式中完成。

引用类型的dynamic_cast

1
2
3
4
5
6
7
8
9
10
#include<typeinfo>
//不存在空引用,所以错误处理不同于指针类型的dynamic_cast
void f(const Base &b)
{
try{
const Derived &d=dynamic_cast<const Derived&> (b);
}catch(bad_cast){
//处理类型转换失败
}
}

说明

未定义错误并不一定报错,只是不同编译器可能结果不同,代码中应该避免出现,或者在理解底层原理的情况下谨慎使用

参考资料

  • C++ Primer.第五版