• 第11课 新型的类型转换


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

    (1)强制类型转换形式

      ①(Type)(Expression)

      ②Type(Expression)   //老式的

    【编程实验】粗暴的类型转换  11-1.cpp

    #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

     

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

    pc = static_cast<char*>(pi);//oops

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

    在类层次间进行转换时上行转换static_castdynamic_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);

    char*pc = reinterpret_cast<char*>(&i);

     

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

     

    //以下错,要用static_cast

    c = reinterpret_cast<char>(i);

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

    dynamic_cast

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

    ②用于有交叉关系的类指针之间(如,继承于同一父类的两个子类间的转换)

     

    详见后面章节的分析

    dynamic_cast具有类型检查的功能。

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

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

    【实例分析】新式类型转化初探  11-2.cpp

    #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); 
    
    }
    
     
    
    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)

  • 相关阅读:
    【Android开发学习笔记】【高级】【随笔】插件化——初探
    【Android测试】【第十三节】Uiautomator——如何组织好你的测试代码(项目实战)
    【Android测试】【第十二节】Uiautomator——API详解
    【Android测试】【第十一节】Uiautomator——简介
    【Android测试】【第十节】MonkeyRunner—— 录制回放
    【Android测试】【第九节】MonkeyRunner—— 初识
    poj 1475 推箱子
    leetcode Ch3-DFS & Backtracking I
    Windows Socket和Linux Socket编程的区别 ZZ
    Linux网络编程入门 (转载)
  • 原文地址:https://www.cnblogs.com/hoiday/p/10089278.html
Copyright © 2020-2023  润新知