C语言的强制类型转换
一般形式
(类型说明符)(表达式)
功能
把表达式的运算结果强制转换成类型说明符所表示的类型。
例如
(int)(x+y)把x+y的结果转换为整型。
自动转换
自动转换是在源类型和目标类型兼容以及目标类型广于源类型时发生一个类型到另一类的转换。
注意
-
表达式要用括号括起来,否则就只转换最近的单个变量,如(int)x+y就只把x转换成int型之后再与y相加。
-
无论是强制转换还是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,并不改变数据说明时对该变量定义的类型。
C++的强制类型转换
C++除了能使用C语言的强制类型转换外,还新增了四种强制类型转换:
- static_cast
- dynamic_cast
- const_cast
- reinterpret_cast
这四种强制类型转换主要用于继承关系类间的强制转化,其一般形式为:
static_cast<new_type>(expression)
dynamic_cast<new_type>(expression)
const_cast<new_type>(expression)
reinterpret_cast<new_type>(expression)
static_cast
static_cast把expression转换为new_type类型,可以转换指针,编译时检查,但没有运行时类型检查来保证转换的安全性。
static_cast常用于基类(父类)和派生类(子类)之间指针或引用的转换,注意,进行上行转换,即把派生类的指针或引用转换成基类表示,是安全的,进行下行转换,即把基类指针或引用转换成派生类表示,由于没有动态类型检查,所以是不安全的。
dynamic_cast
dynamic_cast主要用于类层次间的上行转换和下行转换,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的,在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
当转换的目标类型是引用类型时,如果引用转换失败,会抛出std::bad_cast异常:
void func(const Base & base)
{
try
{
const Derived & derived = dynamic_cast<const Base &>(base);
}
catch(std::bad_cast)
{
// 类型转换失败时的处理
}
}
const_cast
const_cast用于修改类型的const或volatile属性,除了const或volatile修饰之外,new_type和expression的类型是一样的。
// 去掉const常量const属性
const int g1 = 20;
int* h1 = const_cast<int*>(&g1);
// 去掉const引用const属性
const int g2 = 20;
int& h2 = const_cast<int&>(g2);
// 去掉const指针const属性
const char* g3 = "hello";
char* h3 = const_cast<char*>(g3);
reinterpret_cast
reinterpret_cast可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针,先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值。错误的使用reinterpret_cast很容易导致程序不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast的方式。
static_cast和reinterpret_cast的区别主要在于多重继承,如:
#include <string>
#include <iostream>
using namespace std;
class A
{
public:
int m_a;
};
class B
{
public:
int m_b;
};
class C : public A, public B {};
int main()
{
C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
return 0;
}
运行结果:
前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换。所以谨慎使用reinterpret_cast。