首页 > 代码库 > C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)

C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)

 

一.static_cast

static_cast 只能用于良性转换,这样的转换风险较低,一般不会发生什么意外,如:

#include <iostream>#include <cstdlib>using namespace std;class Complex{public:    Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ }public:    operator double() const { return m_real; }  //类型转换函数private:    double m_real;    double m_imag;};int main(){    //下面是正确的用法    int m = 100;    Complex c(12.5, 23.8);    long n = static_cast<long>(m);  //宽转换,没有信息丢失    char ch = static_cast<char>(m);  //窄转换,可能会丢失信息    int *p1 = static_cast<int*>( malloc(10 * sizeof(int)) );  //将void指针转换为具体类型指针    void *p2 = static_cast<void*>(p1);  //将具体类型指针,转换为void指针    double real= static_cast<double>(c);  //调用类型转换函数       //下面的用法是错误的    float *p3 = static_cast<float*>(p1);  //不能在两个具体类型的指针之间进行转换    p3 = static_cast<float*>(0X2DF9);  //不能将整数转换为指针类型    return 0;}

二.const_cast

const_cast用来去掉表达式的 const 修饰或 volatile 修饰。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型。如:

#include <iostream>using namespace std;int main(){    const int n = 100;    int *p = const_cast<int*>(&n);    *p = 234;    cout<<"n = "<<n<<endl;    cout<<"*p = "<<*p<<endl;    return 0;}

运行结果:

n = 100
*p = 234

&n用来获取 n 的地址,它的类型为const int *,必须使用 const_cast 转换为int *类型后才能赋值给 p。由于 p 指向了 n,并且 n 占用的是栈内存,有写入权限,所以可以通过 p 修改 n 的值。

至于为什么通过 n 和 *p 输出的值不一样呢?这是因为 C++ 对常量的处理更像是编译时期的#define,是一个值替换的过程,代码中所有使用 n 的地方在编译期间就被替换成了 100。换句话说,第 8 行代码被修改成了下面的形式:

cout<<"n = "<<100<<endl;

这样以来,即使程序在运行期间修改 n 的值,也不会影响 cout 语句了。

三.reinterpret_cast 

reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高

#include <iostream>using namespace std;class A{public:    A(int a = 0, int b = 0): m_a(a), m_b(b){}private:    int m_a;    int m_b;};int main(){    //将 char* 转换为 float*    char str[]="http://c.biancheng.net";    float *p1 = reinterpret_cast<float*>(str);    cout<<*p1<<endl;    //将 int 转换为 int*    int *p = reinterpret_cast<int*>(100);    //将 A* 转换为 int*    p = reinterpret_cast<int*>(new A(25, 96));    cout<<*p<<endl;       return 0;}

运行结果:

3.0262e+29
25

个人感觉这个关键字很危险,所以不推荐使用.

四.dynamic_cast

dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。

有以下两点需要注意:

1).newType 和 expression 必须同时是指针类型或者引用类型。换句话说,dynamic_cast 只能转换指针类型和引用类型,其它类型(int、double、数组、类、结构体等)都不行。

2).对于指针,如果转换失败将返回 NULL;对于引用,如果转换失败将抛出std::bad_cast异常。

例:

#include <iostream>using namespace std;class A{public:    virtual void func() const { cout<<"Class A"<<endl; }private:    int m_a;};class B: public A{public:    virtual void func() const { cout<<"Class B"<<endl; }private:    int m_b;};class C: public B{public:    virtual void func() const { cout<<"Class C"<<endl; }private:    int m_c;};class D: public C{public:    virtual void func() const { cout<<"Class D"<<endl; }private:    int m_d;};int main(){    A *pa = new A();    B *pb;    C *pc;       //情况①    pb = dynamic_cast<B*>(pa);  //向下转型失败    if(pb == NULL){        cout<<"Downcasting failed: A* to B*"<<endl;    }else{        cout<<"Downcasting successfully: A* to B*"<<endl;        pb -> func();    }    pc = dynamic_cast<C*>(pa);  //向下转型失败    if(pc == NULL){        cout<<"Downcasting failed: A* to C*"<<endl;    }else{        cout<<"Downcasting successfully: A* to C*"<<endl;        pc -> func();    }       cout<<"-------------------------"<<endl;       //情况②    pa = new D();  //向上转型都是允许的    pb = dynamic_cast<B*>(pa);  //向下转型成功    if(pb == NULL){        cout<<"Downcasting failed: A* to B*"<<endl;    }else{        cout<<"Downcasting successfully: A* to B*"<<endl;        pb -> func();    }    pc = dynamic_cast<C*>(pa);  //向下转型成功    if(pc == NULL){        cout<<"Downcasting failed: A* to C*"<<endl;    }else{        cout<<"Downcasting successfully: A* to C*"<<endl;        pc -> func();    }       return 0;}

运行结果:

Downcasting failed: A* to B*
Downcasting failed: A* to C*
-------------------------
Downcasting successfully: A* to B*
Class D
Downcasting successfully: A* to C*
Class D

 

C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)