C++类型转换

来源:互联网 发布:淘宝怎么买115会员 编辑:程序博客网 时间:2024/06/15 04:43
C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:
TYPE b = (TYPE)a。

C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。


1.const_cast
去掉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;//不能直接转换,errorDerived *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。
0 0
原创粉丝点击