zoukankan      html  css  js  c++  java
  • C++学习之路(八):关于C++提供的强制类型转换

    C语言中提供了旧式的强制类型转换方法。比如:

    int a  =1;

    char *p = (char *)&a;

    上述将a的地址单元强制转换为char类型的指针。这里暂且不说上述转换结果是否合理,但上述这样的强制类型转换,如果转换过程出现问题,对于问题的追踪与排查也比较困难。

    对于C++而言,提供了较为安全的强制类型转换方法,下面进行简单介绍。

    一、static_cast

    对于任何具有明确定义的类型转换,只要不包含底层const,都可以用static_cast。

    主要可以有以下几种转换:

    (1)用于基本数据类型之间的转换,如把int转换为char,把int转换为enum,但这里的转换的安全性需要由开发者自己保证;

    (2)把空指针转换成目标类型的指针,这里有点类似旧式的强制类型转换的void*指针转换,但同样,对指针类型的解析,需要由开发者自己保证

    (3)把任何类型的表达式类型转换为void类型;

    (4)用于类层次结构中父类和子类之间指针和引用的转换。

    上面的几点后续遇到了样例再进行补充,这里给一个转换void*指针的样例说明。

    代码1:

    int a = 1;
    char *q = static_cast<char*>(&a);
    cout<<*q<<endl;

    上述代码不能被编译通过,因为static_cast对于指针的转换,只能接受void*类型,上述&a依然是int型指针,不能通过编译。

    代码2:

    int a = 1;
    char *q = static_cast<char*>((void *)&a);
    cout<<*q<<endl;

    通过将&a转型为void*指针,完成对类型的强制转换,上述代码结果正常输出。

    二、const_cast

    在由const关键字定义的变量,是不能在后续被修改的。比如:

      const int a = 1;

      a = 2;

    上述编译不通过,因为a不能被进行修改。

    这里我们依然先看一个样例:

      

    int func(int &a)
    {
        return 0;
    }
    
    int main(void)
    {
        const int a = 1;
        func(a);
        return 0;
    }

    上述代码中,a是一个const变量,但在func函数中的形参需要一个int型变量。很显然,编译直接报错,因为实参与形参具有不同的类型。如何解决这个问题?这就需要引入const_cast进行类型转换

    const_cast只能改变运算对象的底层const。即对于一个const对象,const_cast可以将其const限定移除。上述代码修改为:

    int func(int *a)
    {
        return 0;
    }
    
    int main(void)
    {
        const int a = 1;
        int *p = const_cast<int*>(&a);
        func(p);
    }

    这里将const的变量a的指针,强制类型转换为非const的指针,在func中传入指针变量,程序即可以成功编译。

    这里就有一个疑问:如果可以const_cast将const变量转换为非const变量,是否意味着,可以对const变量进行修改?如果可以,那是不是违背了const关键字的初衷?   这里再看一个样例代码:

    int main(void)
    {
        const int a = 5;
        const int *p = &a;
        int *q = const_cast<int*>(p);
        
        cout<<&a<<endl;
        cout<<p<<endl;
        cout<<q<<endl;
    
        cout<<*q<<endl;
        *q = 6;
        cout<<*p<<endl;
        cout<<a<<endl;
        return 0;
    }

    a是一个const变量,p是一个const指针指向a,q通过const_cast强制类型转换p得到一个非const指针。

    直接贴出程序结果,再进行分析:

    结果可以看到,&a,p,q的值都是相同的,证明p和q指针都正确指向了a的地址单元。接下来输出*q,为a的原值5,再对*q进行了修改,输出*p,结果为成功修改后的6。但最后输出a变量,发现a变量依然为原值5。

    结论很明显了:对于const变量,仍然不能够修改它本身的值,这是限定符自身的约束。

    三、reinterpret_cast

    关于reinterpret_cast,感觉更比较贴合旧式的强制类型转换。举个例子:

    int a = 1;
    char *q = reinterpret_cast<char*>(&a);
    cout<<*q<<endl;

    上述对于static_cast的使用,需要对&a转换为void*才能够进行,但使用reinterpret_cast则可以直接进行转换。reinterpret_cast本质上依赖于机器。

    四、dynamic_cast

    关于dynamic_cast,用法比较丰富,会再之后进行讨论。

    结论:对于一条强制类型转换的语句,都应该反复斟酌是否能用其他方式来实现相同的目标,就算实在无法避免,也应用尽量限制类型转换值的作用域,并记录对相关类型的所有假定,这样可以减少错误发生的机会。

  • 相关阅读:
    Oracle安装错误ora-00922(zhuan)
    Context上下文对象(抄书的)
    我的oracle账号
    jquery总结(1)
    JS改变input的value值不触发onchange事件解决方案 (转)
    写表单验证等页面的总结
    表单验证模板2
    Session随便写的(抄书笔记)
    cookie随便写的一点笔记(抄书的)
    Oracle触发器修改数据时同步执行插入该条数据
  • 原文地址:https://www.cnblogs.com/scu-cjx/p/8758512.html
Copyright © 2011-2022 走看看