C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:
TYPE b = (TYPE)a。
去掉const属性:
2.static_cast
类似于C风格的强制转换,静态类型转换。用于:
1). 父类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(父类指针转换成子类指针 建议用dynamic_cast)
2). 基本数据类型转换。enum, struct, int, char, float等。static_cast不能进行无关类型指针之间的转换。(如非基类和子类)
3). 把空指针转换成目标类型的空指针。
4). 把任何类型的表达式转换成void类型。
5). static_cast不能去掉类型的const、volitale属性。
3.dynamic_cast
dynamic_cast 是c++ 提供的支持RTTI的操作符之一。其操作数(类)必须至少有一个虚函数(以提供vtable,供RTTI进行类型识别)来进行运行时的类型识别,否则dynamic_cast只能用来做安全的转换,例如从派生类指针转换成基类指针。
如上所见:编译时类型转换一般只能提供基类向派生类转换(指针),在派生类向基类转换时发生切割现象。其实当没有虚函数时 dynamic_cast 的作用体现不出来。
dynamic_cast的使用必须注意:
1). 使用虚函数以支持RTTI。(已说明)
2).转换失败的时候的处理。
dynamic_cast的参数(就是需要转换的部分)必须是一个指针或者引用,因为只有通过这两钟形式才能获得运行时的类别。
使用指针时:如果转换失败的话dynamic_cast会返回0,所以使用的时候必须加以检查。
使用引用时:由于不可能给引用赋值为空,所以我们不能通过简单的=0 来判断,此时dynamic_cast 转换失败时会抛出bad_cast异常。
4.reinterpret_cast
仅仅重新解释类型,但没有进行二进制的转换:
1). 转换的类型必须是一个指针、引用、算术类型、函数指针或者成员指针。
2). 在比特位级别上进行转换。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。但不能将非32bit的实例转成指针。
3). 最普通的用途就是在函数指针类型之间进行转换。
4). 很难保证移植性。
int doSomething(){return 0;};
//FuncPtr 是一个指向函数的指针,该函数没有参数,返回值类型为 void
typedef void(*FuncPtr)();
//10个FuncPtrs指针的数组让我们假设你希望(因为某些莫名其妙的原因)
//把一个指向下面函数的指针存入funcPtrArray数组:
FuncPtr funcPtrArray[10];
// 如下语句编译错误!类型不匹配,reinterpret_cast可以让编译器以你的方法去看待它们:funcPtrArray
funcPtrArray[0] = &doSomething;
//不同函数指针类型之间进行转换
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);
总结
去const属性用const_cast。
基本类型转换用static_cast。
多态类之间的类型转换用dynamic_cast。
不同类型的指针类型转换用reinterpret_cast。
TYPE b = (TYPE)a。
C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。
去掉const属性:
#include <iostream>
using namespace std;
class CMyClass
{
public:
CMyClass() { m_nNum = 100; }
~CMyClass() {}
public:
int m_nNum;
};
int main()
{
//1.常量指针转化为非常量指针
const CMyClass* pSA = new CMyClass();
cout<<"常量指针转化为非常量指针"<<endl;
//pSA->m_nNum = 99; //直接修改const类型,编译错误
cout<<"const_cast修改前:"<<pSA->m_nNum<<endl;
CMyClass* pSA1 = const_cast<CMyClass*>(pSA);
pSA1->m_nNum = 11;
cout<<"const_cast修改后:"<<pSA->m_nNum<<endl<<endl;;
//2.常量引用转化为非常量引用
cout<<"常量引用转化为非常量引用"<<endl;
CMyClass sa;
cout<<"const_cast修改前:"<<sa.m_nNum<<endl;
const CMyClass& sa1 = sa;
CMyClass& sa2 = const_cast<CMyClass&>(sa1);
sa2.m_nNum = 22;
cout<<"const_cast修改后:"<<sa.m_nNum<<endl<<endl;
//3.将常量转化为非常量引用
cout<<"将常量转化为非常量引用"<<endl;
const CMyClass cmc;
cout<<"const_cast修改前:"<<cmc.m_nNum<<endl;
CMyClass& mc = const_cast<CMyClass&>(cmc);
mc.m_nNum = 33;
cout<<"const_cast修改后:"<<cmc.m_nNum<<endl;
return 0;
}
2.static_cast
类似于C风格的强制转换,静态类型转换。用于:
1). 父类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(父类指针转换成子类指针 建议用dynamic_cast)
2). 基本数据类型转换。enum, struct, int, char, float等。static_cast不能进行无关类型指针之间的转换。(如非基类和子类)
3). 把空指针转换成目标类型的空指针。
4). 把任何类型的表达式转换成void类型。
5). static_cast不能去掉类型的const、volitale属性。
int n = 6;
double d = static_cast<double>(n); // 基本类型转换
int *pn = &n;
double *d = static_cast<double *>(&n) //无关类型指针转换,编译错误
void *p = static_cast<void *>(pn); //任意指针类型转换成void*类型
3.dynamic_cast
dynamic_cast 是c++ 提供的支持RTTI的操作符之一。其操作数(类)必须至少有一个虚函数(以提供vtable,供RTTI进行类型识别)来进行运行时的类型识别,否则dynamic_cast只能用来做安全的转换,例如从派生类指针转换成基类指针。
#include <iostream>
using namespace std;
class Base1
{
public:
virtual void f() {cout<<"Base1: f()"<<endl;}
};
class Base2
{
public:
virtual void g() {cout<<"Base2: g()"<<endl;}
};
class Derived : public Base1, public Base2
{
public:
virtual void f() {cout<<"Derived: f()"<<endl;}
virtual void g() {cout<<"Derived: g()"<<endl;}
};
int main()
{
Derived d;
Base1 *base1 = &d;
base1->f(); //输出是"Derived: f()"(覆盖)
//Derived *dd = base1; //不能直接转换,error
Derived *dd = static_cast<Derived*>(base1); //同样OK,但是不能提供判断
dd->f(); //输出同样是 "Derived: f()",编译时确定的
Base2 *base2 = &d;
base2->g(); //输出是"Derived: g()"
//base2->f(); //error
//Base1 *base11=static_cast<Base1*>(base2); //不能运行时识别
Base1 *base11 = dynamic_cast<Base1*>(base2);
base11->f(); //输出"Derived: f()"
return 0;
}
如上所见:编译时类型转换一般只能提供基类向派生类转换(指针),在派生类向基类转换时发生切割现象。其实当没有虚函数时 dynamic_cast 的作用体现不出来。
dynamic_cast的使用必须注意:
1). 使用虚函数以支持RTTI。(已说明)
2).转换失败的时候的处理。
dynamic_cast的参数(就是需要转换的部分)必须是一个指针或者引用,因为只有通过这两钟形式才能获得运行时的类别。
使用指针时:如果转换失败的话dynamic_cast会返回0,所以使用的时候必须加以检查。
使用引用时:由于不可能给引用赋值为空,所以我们不能通过简单的=0 来判断,此时dynamic_cast 转换失败时会抛出bad_cast异常。
4.reinterpret_cast
仅仅重新解释类型,但没有进行二进制的转换:
1). 转换的类型必须是一个指针、引用、算术类型、函数指针或者成员指针。
2). 在比特位级别上进行转换。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。但不能将非32bit的实例转成指针。
3). 最普通的用途就是在函数指针类型之间进行转换。
4). 很难保证移植性。
int doSomething(){return 0;};
//FuncPtr 是一个指向函数的指针,该函数没有参数,返回值类型为 void
typedef void(*FuncPtr)();
//10个FuncPtrs指针的数组让我们假设你希望(因为某些莫名其妙的原因)
//把一个指向下面函数的指针存入funcPtrArray数组:
FuncPtr funcPtrArray[10];
// 如下语句编译错误!类型不匹配,reinterpret_cast可以让编译器以你的方法去看待它们:funcPtrArray
funcPtrArray[0] = &doSomething;
//不同函数指针类型之间进行转换
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);
总结
去const属性用const_cast。
基本类型转换用static_cast。
多态类之间的类型转换用dynamic_cast。
不同类型的指针类型转换用reinterpret_cast。