• [C++](27)强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast


    引入

    C语言的类型转换

    在C语言中,如果赋值运算符左右两侧的类型,形参与实参的类型,函数返回值的类型与接收值的类型不同,就需要发生类型转换。C语言存在两种类型转换:隐式类型转换显式类型转换

    1. 隐式类型转换:编译器在编译阶段自动进行,能转则转,不能转则编译失败。
    2. 显式类型转换:程序员自己处理。

    缺陷:

    1. 转换的可视性较差, 所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。
    2. 隐式类型转换在某些情况下会出问题,比如数据精度的丢失
    3. 显式类型转换将所有情况都混合在一起,代码不够清晰。

    C++强制类型转换

    C++ 为了增强类型转换的可视性,引入了 4 种强制类型转换的操作符

    • static_cast
    • reinterpret_cast
    • const_cast
    • dynamic_cast

    C++ 兼容C语言的强制类型转换,但还是希望大家使用新的强制类型转换操作符,以此来提高规范性,可读性,降低出错率。

    static_cast

    static_cast 用于非多态类型的转换(静态转换),编译器隐式执行的任何类型都可以用 static_cast ,但它不能用于两个不相关的类型之间的转换。

    double d = 10.24;
    int a = static_cast<int>(d);
    cout << a << endl;	//10
    

    reinterpret_cast

    reinterpret_cast 可以用于两个不相近的类型之间的转换

    比如用指针转int类型,只能用 reinterpret_cast ,用 static_cast 会报错。

    int* p = &a;
    //int x = static_cast(p); // 报错:E0171	类型转换无效
    int x = reinterpret_cast<int>(p);
    cout << x << endl;
    

    const_cast

    用于去除变量的 const 属性,方便赋值

    如以下情景,不能使用reinterpret_cast

    const int ca = 2;
    //int* pi = reinterpret_cast(&ca); //报错 E0694	reinterpret_cast 无法丢掉常量或其他类型限定符
    int* pi = const_cast<int*>(&ca);
    *pi = 3;
    cout << ca << endl;
    cout << *pi << endl;
    

    这里就有个小问题了,结果是什么?

    • 答案:2 3,这里涉及编译器的优化,被 const 修饰的 ca 编译器不认为它会被修改了,所以访问的时候直接到缓存或者寄存器去取,用 *pi 修改了内存中的值影响不到缓存或寄存器,所以最后打印的 ca 还是 2。

    如果你希望编译器去内存中取 const 变量,可以在前面加 volatile,此时的结果就是 3 3 了。

    volatile const int ca = 2;
    
    • 因为该关键字会去掉 const 属性,所以比较不安全,如果你不确定要去掉 const 属性,那就用 reinterpret_cast

    dynamic_cast

    规范向下转换,转换是安全的

    • 向上转换:子类对象指针/引用转换成父类指针/引用
    • 向下转换:父类对象指针/引用转换成子类指针/引用

    对象是天然支持向上转换的(切片),但是不支持向下转换。

    注意:

    1. dynamic_cast 只能用于父类含有虚函数的类
    2. dynamic_cast 会先检查是否能转换成功,能成功则转换,不能则返回 0

    利用它我们可以检查一个父类指针是指向子类对象还是父类对象:

    • 指向父类对象的父类指针转换成子类指针,会出现越界,所以转换失败。
    • 指向子类对象的父类指针转换成子类指针,没有问题,转换成功。
    class A
    {
    public:
        virtual void f() {} // 父类必须有虚函数才能用dynamic_cast
    };
    
    class B : public A
    {};
    
    void fun(A* pa)
    {
        if (dynamic_cast<B*>(pa))
        {
            cout << "转换成功" << endl;
        }
        else
        {
            cout << "转换失败" << pa << endl;
        }
    }
    
    void test2()
    {
        A a;
        B b;
        fun(&a);
        fun(&b);
    }
    //转换失败0093FC38
    //转换成功
    
    • 所以我们说它是安全的,因为它能检测到你的指针能不能转换,不能转换就不转。
    • 在多态类型(父类有虚函数)的情况下进行向下转换,推荐使用 dynamic_cast ,更加安全。
  • 相关阅读:
    P1394 山上的国度 题解
    RHCSA3
    Map 接口和常用方法
    作为移动开发你不能不了解的编译流程
    Linux 查看内存使用情况的几种方法
    声纹技术(一):声纹技术的前世今生
    Hadoop HA集群全是standBy解决办法
    杭州热身 思维训练
    计算机视觉的相机选型
    HDU 3549 基础网络流EK算法 Flow Problem
  • 原文地址:https://blog.csdn.net/CegghnnoR/article/details/127127156