• 【C++】C++的类型转换


    1. C语言中的类型转换

    在C语言中,经常会出现一种情况:运算符两边的类型不同,或者形参实参类型不匹配,此时就会发生类型转化。在C语言中,类型转化分为两种:隐式类型转换和显式类型转换

    1. 隐式类型转换:编译器在变异阶段自动进行,如果能转换就自动转换,不能就报错
    2. 显示类型转换:用户自己处理
    void test1()
    {
        int i = 1;
        // 隐式类型转换
        double d = i;
        printf("%d, %.2f\n" , i, d);
        int* p = &i;
        // 显示的强制类型转换
        int address = (int)p;
        printf("%x, %d\n" , p, address);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    隐式类型转化有些情况下可能会出问题:

    1. 比如数据精度丢失
    2. 显式类型转换将所有情况混合在一起,代码不够清晰

    2. C++中的类型转换

    由于C语言的类型转换的缺陷,C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:static_castreinterpret_castconst_castdynamic_cast

    2.1 static_cast

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

    用法:static_cast(variablename);其中typename是将要转换的类型,variablename是要被转换的变量。

    void test1()
    {
        double d = 12.34;
        int a = static_cast<int>(d);
        int b = d;
        cout<< a << " " << b <<endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总结:static_cast对标C语言类型转换的隐式类型转换,要求两个类型必须要相关

    2.2 reinterpret_cast

    reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换 为另一种不同的类型

    void test2()
    {
        int a = 12;
        //int* p = static_cast(a);//这里使用static_cast就会报错
        int* p = reinterpret_cast<int*>(a);
        cout << p << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总结:reinterpret_cast对标的是C语言的强制类型转换,不要求两个类型是相关类型

    2.3 const_cast

    const_cast最常用的用途就是删除变量的const属性,方便赋值

    void test3()
    {
        const int a = 10;
        //a = 20;//这里由于a是const修饰的变量,所以不能修改
        int* p = const_cast<int*>(&a);
        *p = 20;
        cout << a << " " << *p << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    拓展知识:如果运行上述的test3代码就会发现,打印出来的a*p的值并不一样,这是什么原因呢?

    image-20230928164618764

    这是因为对于const修饰的变量,编译器会认为它不会被修改,所以会存放在一个寄存器内部,每次访问的时候直接访问寄存器内部的值,所以不会更改。如果想要让他每次都从内存中访问的话,需要加上volatile关键字。

    image-20230928164919653

    2.4 dynamic

    dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

    这里补充一下向上转换向下转换的概念:

    向上转换:由子类(对象/指针/引用)向父类(对象/指针/引用)的转换

    向下转换:由父类(对象/指针/引用)向子类(对象/指针/引用)的转换

    其中,向上转换是天然被允许的,中间没有类型转换,也不会产生临时对象,但是向下转换可能会出现数组越界之类的问题,因此是不安全的

    class A
    {
    public:
        virtual void f() {}
        
        int _a = 1;
    };
    class B : public A
    {
    public:
        void f() {}
        int _b = 2;
    };
    void func(A* ptr)
    {
        B* bptr = (B*)ptr;
        cout << bptr->_b << endl;
        cout << bptr->_a << endl;
    }
    void test4()
    {
        A aa;
        B bb;
        func(&aa);
        func(&bb);
    }
    
    • 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

    这里对于A类型的对象,如果要访问_b成员就会出现越界访问的问题。

    dynamic_cast 的作用就是将一个父类对象的指针/引用转换为子类对象的指针或引用 (向下转型)。需要注意的是:

    • dynamic_cast只能用于父类含有虚函数的类。
    • dynamic_cast会检查是否能转换成功,能则进行转换,不能则返回nullptr。
    void func(A* ptr)
    {
        //B* bptr = (B*)ptr;
        B* bptr = dynamic_cast<B*>(ptr);
        if(bptr == nullptr)
        {
            cout << "类型转换错误:出现向下转换" << endl;
            return;
        }
        cout << bptr->_b << endl;
        cout << bptr->_a << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20231001180133033

    注意:一般情况下我们应该避免使用强制类型转换,因为强制类型转换关闭或挂起了正常的类型检查;所以每次在使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方法达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。


    本节完…

  • 相关阅读:
    通讯录的动态版本
    docker入门加实战—docker安装并配置阿里云加速
    使用Dapr和Tye启动服务
    Vue 商场首页头部布局
    企业微信SCRM的那些事儿
    Redis 命令 和 数据类型 您知道多少
    设计模式(八)组合
    PAT 1017 A除以B
    深入探讨I/O模型:Java中的阻塞和非阻塞和其他高级IO应用
    奇安信笔试C++
  • 原文地址:https://blog.csdn.net/weixin_63249832/article/details/133467569