C++强制类型转换

本文介绍C++的四种强制类型转换,转载请注明出处。

一、const_cast:

  去除指针或引用的const属性。

1、转化常量指针为非常量的指针,并且仍然指向原来的对象; 

2、转化常量引用为非常量的引用,并且仍然指向原来的对象; 

3、const_cast一般用于修改指针。如const int *ptr形式。

用法:

#include <iostream>
using namespace std;

void main(){
    cout << "const_cast测试" << endl;
    int ary[4] = { 1, 2, 3, 4 };
    const int *c_ary = ary;
    //c_ary[0] = 5;//错误,常量不能改变
    int *ary2 = const_cast<int*>(c_ary);//const_cast将常量指针转化为非常量指针
    ary2[0] = 5;//正确

    int a = 2;
    const int &c_a = a;
    //c_a = 5;//错误,常量不能改变
    int &a2 = const_cast<int&>(c_a);//const_cast将常量引用转化为非常量引用
    a2 = 5;//正确

    const int c_val = 3;
    int &ref_val = const_cast<int&>(c_val);//得到去const的引用
    int *ptr_val = const_cast<int*>(&c_val);//得到去const的指针
    
    system("pause");
}

二、static_cast

  转换数据类型,类的上下行转换。

1、转换数据类型,由于没有运行时类型检查来保证转换的安全性,不安全;

2、类的上下行转换,由于没有运行时类型检查,下行转换不安全;

3、static_cast不能转换掉原有类型的const、volatile、或者 __unaligned属性;

c++ 的任何的隐式转换都是使用 static_cast 来实现。

#include <iostream>
using namespace std;

void main(){
    cout << "static_cast测试" << endl;
    float f_pi = 3.1415;
    int i_pi = static_cast<int>(f_pi);

    //类的上下行转换
    class Base{
    };
    class Derived :public Base{
    };

    //上行转换 Derived->Base,安全
    Derived derived;
    Base *base_ptr = static_cast<Base*>(&derived);

    //下行转换 Base->Derived,由于没有动态类型检查,编译能通过但不安全
    Base base;
    Derived *derived_ptr = static_cast<Derived*>(&base);
    
    system("pause");
}

 三、dynamic_cast

  安全的上下行转换。

  上行转换(子类到基类的指针转换),dynamic_cast成功转换,运行正常且输出预期结果。而下行转换(基类到子类的转换),dynamic_cast在转换时也没有报错,但是输出给base2deri是空指针,说明dynami_cast在程序运行时对类型转换对“运行期类型信息”(Runtime type information,RTTI)进行了检查,是安全的(转换后为空指针,不会指向未知内存,保证了使用安全)。而用static_cast由于没有动态类型检查,编译能通过但不安全。

#include <iostream>
using namespace std;

class Base{
public:
    Base() {}
    ~Base() {}
    void print() {
        std::cout << "This is Base" << endl;
    }

    virtual void virtual_foo() {}
};

class Derived : public Base{
public:
    Derived() {}
    ~Derived() {}
    void print() {
        std::cout << "This is Derived" << endl;
    }

    virtual void virtual_foo() {}
};

void main(){
    cout << "dynamic_cast测试" << endl;
    //上行转换 Derived->Base
    Derived *derived = new Derived();
    derived->print();//输出This is Derived
    Base* deri2base = dynamic_cast<Base*>(derived);
    if (deri2base != nullptr){
        derived->print();//输出This is Derived
    }

    //下行转换 Base->Derived
    Base *base = new Base();
    base->print();//输出This is Base
    Derived* base2deri = dynamic_cast<Derived*>(base);
    if (base2deri != nullptr){//base2deri为空,不进行打印
        base2deri->print();
    }
    
    Base *base2 = new Derived();
    base2->print();//输出This is Base
    //Derived* deri2 = new Base();//错误。不能直接将Base*转换为Derived*,即不能直接下行转换。

    delete derived;
    derived = nullptr;
    delete base;
    base = nullptr;

    system("pause");
}

输出:

四、reinterpret_cast

  进行无关类型的转换

  用在任意的指针间的转换,任意引用间的转换,指针和足够大的整型之间的转换,整型到指针的转换。

#include <iostream>
using namespace std;

void main(){
    int *p = new int(5);
    cout << "p的地址: " << hex << p << endl;//std::hex用于以16进制输出十进制数
    int p_addr = reinterpret_cast<int>(p);
    cout << "p_addr的值: " << hex << p_addr << endl;
    
    delete p;
    p = nullptr;

    system("pause");
}

输出:

可见已经将指针p转换为了int型,指针p的地址的值和整形p_addr的数值相同,都为0x44b4b8。

原文地址:https://www.cnblogs.com/zeppelin5/p/10075569.html