C++ 类型转换

来源:互联网 发布:网络的话 编辑:程序博客网 时间:2024/05/05 19:06

一、static_cast
    static_cast用于在相关类型的指针之间进行转换,还可以显式地指向标准数据类型的类型转换。用于指针时,static_cast实现了基本的编译阶段检查,确保指针被转换为相关类型。在C语言中,可将一个对象的指针转换为完全不相关的类型,而编译器也不会报错。使用static_cast可将指针向上转换为基类类型,也可向下转为派生类型。
    CAnimal *pBase = new CDog;
    CDog* pDog = static_cast(pBase);  //ok
    CUnrelated* pUnrelated = static_cast(pBase); //error
    static_cast只验证指针类型是否相关,而不会执行任何运行阶段检查。如果是下面的情况也不会报错:
    CAnimal *pBase = new CAnimal;
    CDog* pDog = static_cast(pBase);  //compile ok but run error
    其中pDog指向的是一个不完整的CDog对象,因为实际上他指向的是CAnimal对象类型。这会导致在运行阶段,使用该指针调用CDog的方法会导致意外的结果。
二、dynamic_cast
    动态类型转换在运行阶段执行类型转换,可以检查dynamic_cast操作的结果以判断类型转换是否成功。
    CAnimal *pBase = new CDog;
    CDog* pDog = static_cast(pBase);  //ok
    if (pDog) //check for sucess of cast
        pDog->move();
    给定一个基类对象,程序员可能不确定它属于哪种派生类型,这时可以使用dynamic_cast在运行阶段判断其类型,并在安全时使用转换后的指针。
    void DetermineType(CAnimal *pAnimal)
    {
         CDog* pDog = static_cast(pAnimal);
         if(pDog)
            pDog->move();
        CCat* pCat = static_cast(pAnimal);
         if(pCat)
            pCat->run();
    }   
三、reinterpret_cast     
   reinterpret_cast是C++中与C风格类型转换最接近的类型转换运算符。它不管类型是否相关,强制编译器接收static_cast通常不允许的类型转换。通常用于低级程序(如驱动程序).
四、const_cast
   const_cast让程序员关闭对象的访问修饰符const。
   CSomeClass
   {
     public:
     void show(); // ought to be a const member
   }
   如果是下面这种情况,将会编译错误
   void showAllData{const CSomeClass& mData}
   {
     mData.show(); // compile error
   }
   在这种情况下,调用show的语法如下:
   void showAllData{const CSomeClass& mData}
   {
    CSomeClass& rData = const_cast(mData);
     rData.show(); // ok
   }
   另外,const_cast也可用于指针。
五、static_cast和reinterpret_cast区别
    C++通过指针来访问成员的过程,实际上是根据指针的类型,找到改类定义,并从中找到要访问的成员的地址偏移,然后从对象指针开始加上偏移,便得到了成员的地址,然后进行访问操作。所以类定义的作用之一在于,确定成员的内存偏移。
    static_cast会在编译期将指针在类的内存空间内移动,并最终指向到你转换到的内存上。在上面的例子中,当将CAnimal*的指针转型为CDog*型指针时,实际上将指针的数值修改了,指向了内存中CDog类的开头位置。当使用转换后的指针访问CDog的成员时,先到CDog类定义查到CDog的内存分布,然后进行指针偏移,访问。一切都是正确的。
    reinterpret_cast并不会在转型是修改指针的值,而是告诉编译期,这个指针是某个类型的指针,仅此而已。所以当使用此转型方式转换CAnimal*的指针到CDog*类型时,指针仍然指向原来的位置,即CAnimal*的开头。这时如果访问CDog*的成员move,那么先到CDog上查到move的地址偏移,那么你实际是将指针偏移到了CAnimal类的xx成员处,访问的是xx的内容。这种错误是编译器不明白的,你的程序即将崩溃。所以,请谨慎使用reinterpret_cast。