zoukankan      html  css  js  c++  java
  • 第11课 新型的类型转换

    1. C方式的强制类型转换

    (1)转换形式

      ①(Type)(Expression)

      ②Type(Expression) //老式的

    【编程实验】粗暴的类型转换

    #include <stdio.h>
    
    typedef void PF(int);
    
    struct Point
    {
        int x;
        int y;
    };
    
    int main()
    {
        int v = 0x12345;
        PF* pf = (PF*)v;
        char c = char(v);//老式写法,很像函数调用
        Point* p = (Point*)v;
    
        pf(5);
    
        printf("p->x = %d
    ", p->x);
        printf("p->y = %d
    ", p->y);
    
        return 0;
    }

    (2)强制类型转换存在的问题

      ①过于粗暴:任意类型之间都可以进行转换,编译器很难判断其正确性

      ②难于定位:在源码中无法快速定位所有使用强制类型转换的语句

    2. C++中新式的4种强制类型转换

    (1)用法:xxx_cast(Type)(Expression)

    (2)4种类型

    类型

    适用范围

    举例

    备注

    static_cast

    基本类型之间(可相互隐式转换)

    ②不能用于基本类型的指针之间(因为该类型的指针间不能互相隐式转换

    ③类与子类对象之间的转换或类指针间转换。(子类对象可隐式转换为父类(单向,反之不行。指针类型也一样)

    int i = 0;

    char c = 'A';

    int* pi = &i;

    char* pc = &c;

    c = static_cast<char>(i); //ok,c =i 或 i=c(即可双向隐式转换

    //不能用于基本类型的指针间转换

    pc = static_cast<char*>(pi);//oops,因为 pi不能隐式转换为pc

    ①一般适用于两者间可隐式转换的类型(双向或单向均可)。

    ②编译时检查,可用于非多态类指针间的转换,但不支持交叉转换。

    ③在类层次间进行转换时,上行转换static_cast与dynamic_cast效果是一样的,但下行转换时dynamic_cast具有类型检查功能,比static_cast更安全。

    const_cast

    目标类型(即尖括号内的类型)必须是指针或引用

    //i有内存,因别名,每次从内存读取i

    const int& i = 1;//i为引用

    int& a = const_cast<int&>(i);

    const int j = 1;

    //为j分配内存,但不会去用它,从符号表中取j

    int&  b = const_cast<int&>(j);

    a = 5; //i==5;a==5;

    b = 3; //j==1,b==3;

    用于去除变量的const属性

    reinterpret_cast

    ①用于指针类型间

    ②用于整数和指针类型之间

    typedef void PF(int);

    int i = 0;

    char c = 'c';

    int* pi = reinterpret_cast<int*>(&c); //因为&c(char*类型)不能隐式转为pi。

    char*pc = reinterpret_cast<char*>(&i);//&i不能隐式转为char*

    PF*pf= reinterpret_cast<PF*>(0x12345678);

    //以下错,要用static_cast

    c = reinterpret_cast<char>(i); //oops,因为i可隐式转为c。

    ①一般适用于不能隐式转换的类型之间的转换(双向均不能)

    ②reinterpret_cast直接从二进制位进行复制,是一种极其不安全的转换。

    dynamic_cast

    ①用于有继承关系的类指针间。

    ②用于有交叉关系的类指针之间(即继承图上通过继承路径的可达的两个类之间,如,多继承的两个基类之间等。)

    详见后面章节的分析

    ①dynamic_cast具有类型检查的功能,目标类型必须是类的指针或引用

    ②运行时检查,用于多态的类型转换(上转,下转和交叉转换),只能转换指针和引用且需要虚函数的支持,才不会报错。而static_cast转换,即使基类没有虚函数,编译也不会报错,但这种转换不完全。

    ③dynamic_cast支持交叉转换,而satic_cast不支持这种转换

    【实例分析】新式类型转化初探

    #include <stdio.h>
    
    void static_cast_demo()
    {
        int i = 0x12345;
        char c = 'c';
        int* pi = &i;
        char* pc = &c;
    
        c = static_cast<char>(i);//基本类型
    
        //基本类型的指针间,非法
        //pc = static_cast<char*>(pi);  //pi不能隐式转为pc,须用reinterpret_cast!
    }
    
    void const_cast_demo()
    {
    
        //用常量初始化引用,要分配内存。故j为变量,因加const而成只读变量
        const int& j = 1;//j为引用--》只读变量,说明j不能做为左值而己
        int& k = const_cast<int&>(j); //转为普通引用,k就是j的别名
    
        k = 5;
    
        printf("k = %d
    ", k); //5
        printf("j = %d
    ", j); //5
    
        const int x = 2; //x为常量
        int& y = const_cast<int&>(x);//此时,会为x分配内存
        //int z = const_cast<int>(x);  //oops,目标类型只能是引用或指针
    
        y = 3;
    
        printf("x = %d
    ", x); //2
        printf("y = %d
    ", y); //3
        printf("&x = %d
    ", &x);
        printf("&y = %d
    ", &y); //x与y的内存地址是相同的
    }
    
    void reinterpret_cast_demo()
    {
        int i = 0;
        char c = 'c';
        int* pi = &i;
        char* pc = &c;
    
        pc = reinterpret_cast<char*>(pi); //ok,指针间
        pi = reinterpret_cast<int*>(pc);  //ok,指针间
        pi = reinterpret_cast<int*>(i);   //ok,整数与指针间
        //c  = reinterpret_cast<char>(i);   //oops,基本类型间转换,要用static_cast
    
    }
    
    void dynamic_cast_demo()
    {
        int i = 0;
        int* pi = &i;
        char* pc = dynamic_cast<char*>(pi);//oops,目标类型应为类的指针或引用
    }
    
    int main()
    {
        static_cast_demo();
        const_cast_demo();
    
        reinterpret_cast_demo();
        dynamic_cast_demo();
        return 0;
    }

    3. 小结

    (1)C方式的强制类型转换

      ①过于粗暴;②潜在的问题不易被发现;③不易在代码中定位

    (2)新式类型转换以C++关键字的方式出现

      ①编译器能够帮助检查潜在的问题

      ②非常方便的在代码中定位

      ③支持动态类型识别(dynamic_cast)

  • 相关阅读:
    java并发之hashmap源码
    java并发之hashmap
    java线程池之一:创建线程池的方法
    springAOP之代理模式
    java阻塞队列之LinkedBlockingQueue
    java阻塞队列之ArrayBlockingQueue
    java中的异常
    springboot入门之一:环境搭建(续)
    Unity 游戏框架搭建 2019 (二十三、二十四) 备份与版本号&危险的操作
    Unity 游戏框架搭建 2019 (二十一、二十二) 第三章简介&整理前的准备
  • 原文地址:https://www.cnblogs.com/5iedu/p/5375350.html
Copyright © 2011-2022 走看看