• 每天一点C++——C++中的强制类型转换


    C++中打印数据类型typeid(var).name()

    C中的强制类型转换

    C中的强制类型转换并不改变数据在内存中实际存储的值,只是修改了对这段内存解释的方式。

    因此C语言里面的强制类型转换也就存在了一些几个缺点:

    1. 允许任意类型之间的转换,极不安全,例如误将const指针转为了非const,基类指针转为子类指针等。
    2. 没有安全检查
      测试代码:
    int test_c_cast() {
        short s1 = -1;
        unsigned short s2 = (unsigned short)s1;
        std::cout << "s1: " << s1 << "; s2: " << s2 << "\n";
    
        unsigned short s3 = 32768;
        short s4 = (short)s3;
        std::cout << "s3: " << s3 << "; s4: " << s4 << "\n";
    
        char c1 = -128;
        unsigned short s5 = (unsigned short)c1;
        std::cout << "c1: " << c1 << "; s5: " << s5 << "\n";
    
        int i1 = -800008;
        unsigned short s6 = (unsigned short)i1;
        std::cout << "i1: " << i1 << "; s6: " << s6 << "\n";
    
        unsigned int ui2 = 4294967295;
        float f1 = (float)ui2;
        std::cout << "ui2: " << ui2 << "; f1: " << f1 << "\n";
    
        float f2 = -100.11;
        int i2 = (int)f2;
        std::cout << "i2: " << i2 << "; f2: " << f2 << "\n";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    测试结果:

    s1: -1; s2: 65535
    s3: 32768; s4: -32768
    c1:; s5: 65408
    i1: -800008; s6: 51960
    ui2: 4294967295; f1: 4.29497e+09
    i2: -100; f2: -100.11
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    C++中的强制类型转换

    由于C中强制转换的缺点,C++中引入了一下几种类型转换。

    const_cast

    const_cast常用于修改遍历的const属性,把变量的const属性干掉。返回的是一个变量的指针或者引用。因此模板的值也需要是引用或者指针。
    样例代码:

    int test_cpp_const_cast() {
        const int ci1 = 33;
        //ci1 = 11; // error: assignment of read-only variable
    
        int i2 = const_cast<int&>(ci1);
        i2 = 11;
        std::cout << "ci1: " << ci1 << ", ci1 addr: " << &ci1 <<"; i2: " << i2 << ", i2 addr: " << &i2 <<"\n";
    
        const int *cpi = new int(44);
        int *i3 = const_cast<int *>(cpi);
    
        *i3 = 22;
        std::cout << "*cpi: " << *cpi << "; *i3: " << *i3 << "\n";
        delete cpi;
        const int ci2 = 55;  //不加volatile的话,直接读取的是寄存器的值,下面更新后值不会更新
        int *i4 = const_cast<int *>(&ci2);
    
        *i4 = 77;
        std::cout << "ci2: "  << ci2 << ", ci2 addr: " << &ci2 << "; *i4: " << *i4 << ", i4 addr: " << i4 << "\n";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    static_cast

    static_cast会在编译过程中进行安全性检查,相对于dynamic_cast是静态转换。但是不能保证是安全转换,需要程序员自己保证。编译器隐式执行的任何类型转换都可用static_cast。
    通常使用场景:

    1. 用于基类与派生类之间的转换: 向上转换是安全的;向下转换是不安全的。
    2. 用于基础类型之间的转换。有些转换也是不安全的,例如int转char。
    3. void类型指针转为任意其他类型指针
    4. 任意类型指针转为void型指针

    代码样例:

    int test_cpp_static_cast() {
        int i1 = 50000;
        short s1 = static_cast<short>(i1); //不安全转换
        std::cout << "i1: " << i1 << "; s1: " << s1 << "\n";
    
        void * p = malloc(16);
        memset(p, 1, 16);
        unsigned short *s2 = static_cast<unsigned short *>(p);
        std::cout << "s2: " << *s2 << "\n";
        void * p = malloc(16);
        memset(p, 1, 16);
        int *i2 = static_cast<int *>(p); //不安全转换
        std::cout << "i2: " << *i2 << "\n";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    dynamic_cast

    dynamic_cast一般用于基类和派生类之间的转换。在运行时会进行检查,属于动态转换。
    对于向下转换与static_cast的功能相同。对于向上转换dynamic_cast会进行类型检查,更安全。
    几点注意事项:

    1. 要求基类必须有虚函数,否则编译报错
    2. 单继承的时候可以用static_cast进行转换。多继承则只能使用dynamic_cast

    reinterpret_cast

    类似于C的类型转换,并不修改内存中的值,只是指定了内存中值的解释方式。
    用于指针或者引用之间的相互转换。或者将int型转换为指针,将指针转换为int型。

    测试代码:

    int test_cpp_reinterpret_cast() {
        int * pi = new int(55);
        unsigned long long addr = reinterpret_cast<int>(pi);
        std::cout << "pi: " << pi << "; addr: " << addr << "\n";
    
        float *pf = reinterpret_cast<float *>(pi); //不安全转换
        std::cout << "pi: " << pi << "; pf: " << pf << "\n";
        std::cout << "*pi: " << *pi << "; *pf: " << *pf << "\n";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    Ubuntu中kill完全卡死的Pycharm【没办法关闭】
    Flutter 3.19.0 版本新特性
    简单的前端语言
    Java杂学记录
    vscode配置vue
    SpringCloud微服务实践之二 搭建注册中心
    Pandas合并excel表格的两种方式
    Android开发笔记消息推送SDK
    深度解读低门槛钱包赛道:Web3的用户入口
    AI全流程开发难题破解之钥
  • 原文地址:https://blog.csdn.net/itlilyer/article/details/125885704