在c语言的基础上,C++新增加了四种强制类型转换:
static_cast<new_type>(expression)
dynamic_cast<new_type>(expression)
const_cast<new_type>(expression)
reinterpret_cast<new_type> (expression)
其中,new_type为目标数据类型,variable为变量或者表达式
static_cast用于以下类型转换,static_cast在类型转换时,在编译期间会对类型进行检查,运行时不会检查类型转换的安全性
基本数据类型之间的转换:如enum转换为int,int转换为char
将空指针转换为目标类型的空指针
将任何类型的表达式都转换为void类型
将non-const变量
转换为const变量
static_cast还可以转换对象的指针类型,但它不进行运行时类型检查,如用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换
1.将基类转换为派生类:安全
2.派生类转换为基类:不安全
注意:static_cast不能移掉expression中的const,volatile以及_unaligned属性
enum Week
{
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};
Week noday = static_cast<Week>(7) //sucess
Week noday = static_cast<Week>(8) //error
int i = 10;
char c = static_cast<char>(i);//正确,int转换为char
int *pI = NULL;
char *cI = static_cast<void*>(pI);//将int类型空指针转换为char空指针
int i = 10;
const int j = static_cast<const int>(i);//正确,将int型数据转换成const int型数据
const int i = 20;
int ii = static_cast<int>(i);//编译错误,static_cast不能转换掉i的const属性
class B{};
class C : public B{};
voif f(B *pb,C *pC)
{
C* pC1 = static_cast<C*>(pb); //父类转子类,不安全
B* pB1 = static_cast<B*>(pC); //安全,子类转父类
}
上面的第一个类型转换是不安全的。比如,一旦使用pC1调用了一个子类C有而父类B没有的方法,程序就会因越界访问而崩溃。
dynamic_cast是将一个基类对象指针或者引用
转换到继承类类指针或者引用
,dynamic_cast用来检查两者是否有继承关系,因此实际上只接受基于类对象的指针或者引用的转换,转换格式为:
dynamic_cast<new_type*>(expression):new_type必须为有效指针
dynamic_cast<new_type&>(expression):new_type必须为左值
dynamic_cast<new_type&&>(expression):new_type必须为右值
如果 new_type是类指针类型,那么expression也必须是一个指针,如果 new_type 是一个引用,那么 expression 也必须是一个引用。dynamic_cast可以在执行期决定真正的类型。在下行转换时具有类型检查的功能,比static_cast是安全的,如果下行转换是安全的(也就说,如果基类指针或者引用指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 下行转换不安全,这个运算符会传回空指针
(也就是说,基类指针或者引用没有指向一个派生类对象)。
基类中必须包含至少一个虚函数,而static_cast没有这个限制
class B
{
public:
int m_i;
virtual void f();//基类必须有一个虚函数
};
class C:public B
{
public:
char *m_Str[100];
}
void(B* pb,C *pc)
{
if(B *pB = dynamic_cast(pc)){
//使用pB指向的C对象
}
else{
pB = dynamic_cast(pB)
//使用pb指向的B对象
}
}
在上面的代码中,在if语句定义pB,可以完成类型转换和安全性检查两项任务
因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。
void f(const C &c){
try{
const B &b = dynamic_cast<const C&>(c);
//使用b引用的C对象
}
catch(std::bad_cast){
//处理类型转换失败的情况
}
}
const_cast,用于修改类型的const或volatile属性,主要用于去掉const属性,该运算符用来修改类型的const(唯一有此能力的C+±style转型操作符)或volatile属性。除了const 或volatile修饰之外, new_type和expression的类型是一样的。
const_cast < new_type > ( expression )
主要应用场景为:
常量指针转化成非常量的指针,并且仍然指向原来的对象;
常量引用转换成非常量的引用,并且仍然指向原来的对象;
const_cast一般用于修改底指针,如const char *p形式。
const int i = 10;
int *pi = const_cast(&i);//去掉const常量的const属性
const int i = 20;i
int &h = const_cast(i);//去掉const引用const属性
const char *str = "hello";
char *h = const_cast(str);//去掉const指针const属性
reinterpret_cast < new_type > ( expression )
new_type必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值),它是这四种转换运算符中最不安全的,它主要适用于依赖底层实现的编程技术,因为不系统一个类型存储的字节可能是不一样的,所以具有不可移植性、对平台的依赖性强。
代码示例:
#include
using namespace std;
class Data
{
public:
short a;
short b;
};
void delete_ptr(void *p)
{
if(p != nullptr)
{
delete p;
p=nullptr;
}
}
int main()
{
long value = 0xAAAABBBB;
Data *pData = reinterpret_cast<Data*>(&value);
cout << hex << pData->a << endl;
cout << hex << pData->b << endl;
// 不需要释放指针pData的空间,它的地址和变量value相同,会自动释放掉
// delete_ptr(pData);
}
结果为:
BBBB
AAAA