温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

新型的类型转换(九)

发布时间:2020-07-28 16:40:37 来源:网络 阅读:510 作者:上帝之子521 栏目:编程语言

        我们之前在 C 语言进行类型转换是强制类型转换的,这样极易出 bug,还不易查找。格式如下:(Type)(Experssion) 或 Type(Experssion),我们来看个示例代码,看看 C 语言中的强制类型转换

#include <stdio.h>

typedef void(PF)(int);

struct Point
{
    int x;
    int y;
};

int main(int argc, char *argv[])
{
    int v = 0x12345;
    PF* pf = (PF*)v;
    char c = char(v);
    Point* p = (Point*)v;
    
    pf(5);
    
    printf("p->x = %d\n", p->x);
    printf("p->y = %d\n", p->y);
    
    return 0;
}

        编译结果如下

新型的类型转换(九)

        我们看到直接运行段错误,但是它编译是通过的,因此我们如果在大型的项目中是难以查找 bug 的。

        在 C 方式的强制类型转换的过程中,它存在的问题:a> 过于粗暴:任意类型之间都可以进行转换,编译器很难判断其正确性;b> 难于定位:在源码中无法快速定位所有使用强制类型转换的语句。那么强制类型转换在实际工程中是很难完全避免的!如何进行更加安全可靠的转换呢?在 C++ 中出现了新式类型转换,C++ 将强制类型转换分为 4 中不同的类型:a> static_cast;b> const_cast;c> dynamic_cast;d> reinterpret_cast;用法是:xxx_cast<Type>(Expression)。下来我们分别来讲下这四种新式类型转换的特点及要求

        A、static_cast 强制类型转换

        用于基本类型间的转换;不能用于基本类型指针间的转换;用于有继承关系类对象之间的转换和类指针之间的转换。

        B、const_cast 强制类型转换

        用于去除变量的只读属性;强制转换的目标类型必须是指针或引用。

        C、reinterpret_cast 强制类型转换

        用于指针类型间的强制转换;用于整数和指针类型间的强制转换。

        D、dynamic_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);    // error
}

void const_cast_demo()
{
    const int& j = 1;
    int& k = const_cast<int&>(j);
    
    const int x = 2;
    int& y = const_cast<int&>(x);
    
    int z = const_cast<int>(x);    // error
    
    k = 5;
    
    printf("k = %d\n", k);
    printf("j = %d\n", j);
    
    y = 8;
    
    printf("x = %d\n", x);
    printf("y = %d\n", y);
    printf("&x = %p\n", &x);
    printf("&y = %p\n", &y);
}

void reinterpret_cast_demo()
{
    int i = 0;
    char c = 'c';
    int* pi = &i;
    char* pc = &c;
    
    pc = reinterpret_cast<char*>(pi);
    pi = reinterpret_cast<int*>(pc);
    pi = reinterpret_cast<int*>(i);
    c = reinterpret_cast<char>(i);     // error
}

void dynamic_cast_demo()
{
    int i = 0;
    int* pi = &i;
    char* pc = dynamic_cast<char*>(pi);    // error
}

int main()
{
    static_cast_demo();
    const_cast_demo();
    reinterpret_cast_demo();
    dynamic_cast_demo();
    
    return 0;
}

        我们来分析下这个代码,在 static_cast_demo 中,static_cast 不能用于指针间的转换,所以第 11 行会报错。在 const_cast_demo 中,第 16 行定义了一个具有只读属性的变量 j,我们还是可以通过 const_cast 来改变它的属性的。第 19 行定义了一个真正意义上的常量,它会进入到符号表中,但在栈上会为它分配 4 个字节的空间,所以第 20 行的也会成功。const_cast 强制转换的目标类型必须是指针或引用,所以第 22 行会报错。第 26 、 27 行会打印出 5、5;第 31 - 34 会打印出 2、8、后面两个地址是一样的。在 reinterpret_cast_demo 中,reinterpret_cast 用于指针类型间及整数和指针类型间的强制转换,所以第 47 行会报错。在 dynamic_cast_demo 中,第 54 行会报错。我们来看看编译结果

新型的类型转换(九)

        我们分别注释掉这几行,再来编译,看看结果是否如我们所分析的那样

新型的类型转换(九)

        我们看到和我们所分析的是一致的。通过对强制类型转换的学习,总结如下:1、C 方式的强制类型转换:a> 过于粗暴。 b> 潜在的问题不易被发现。 c> 不易在代码中定位;2、新式类型转换以 C++ 关键字的方式出现:a> 编译器能帮助检查潜在的问题。 b> 非常方便的在代码中定位。 c> 支持动态类型识别(dynamic_cast)。


        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI