C++中的强制转换运算符 const_cast,static_cast ,dynamic_cast 和reinterpret_cast的分析

(1)const_cast运算符:  通常用来去掉对象的常量性,但是一般还是不会去改变原来常量的值,这样做只是为了程序编译通过。
该运算符的用法为:
const_cast<type_id>(expression)
将expression表达式的只读性去掉,转换成type_id类型。
其中的type_id只能为指针或者引用才有转换的意义。
因为只有用指针或者引用,让转换后的变量指向同一个地址
才可以达到目的。
eg:

#include <iostream>
using namespace std;

int main()
{
    const int a=2;
    
   int &b= const_cast<int &> (a);//此时b成了a的一个引用,并且把只读性去掉了
     b++;
   int * ptr=const_cast<int *>(&a);//与上面等价
     (*ptr)++;
     
      cout<<"b="<<b<<endl;
      cout<<"*ptr="<<(*ptr)<<endl;
      cout<<"a="<<a<<endl;
      

    return 0;
}


程序输出结果为:
b=4
*ptr=4
a=2
我们取b,ptr,a的地址会发现它们的地址是一样的。但是a由于一开始就声明了为const只读的
所以其值确实没有改变,语言标准要求如此。编译器背后的机理我不明白。

总结:一旦一个变量被声明成了const,则编译器会保证该变量确实不会被修改。我们也确实不要尝试
去修改。使用const_cast去除const限定的目的绝对不是为了修改它的内容,事实上编译器也不会修改。
const_cast我一般用于函数调用的时候,由于函数参数不是cosnt型,而我传递的参数是一个
cosnt型,那么就可以使用该运算符去掉参数的cosnt性,从而去掉编译错误。
相信大家在C++编译器中会遇到大意是:“不能从const int *转换值 int *”。此时该运算符就可以
去掉这个编译错误。

---------------------------------------------------------------------------------
(2)static_cast      主要用于变量的包容性的转化,(即原操作的隐形转化);同时对于类来说,主要用于对象向父转型
该运算符的用法为:
static_cast<type_id>(expresssion)
该运算符在编译时将expression转换成type_id类型。
程序员应该负责转换的安全性。
其实按照我的理解,static_cast运算符就相当于老式的隐式类型转换。
例如:int a=3;
     double d=(double)a;<====>double d=static_cast<double>(a);
     int *ptr=(int *)malloc(100);<====> int *ptr=static_cast<int *>(malloc(100));
另外在类的继承体系中,从下向上转换也可以使用这个运算符,这是一个天然的转换。
-------------------------------------------------------------------------------------

(3)dynamic_cast    主要用于变量向大范围转化,(即原操作的强制转化);对于类来说,就是对象向子类转化
该运算符的用法为:
dynamic_cast<type_id>(expression)
该运算符在运行时将expression表达式转换成type_id类型,作用于一个具有多态性质的类继承体系结构。
type_id为派生类的指针或者引用,expression为基类指针或者引用。
该运算符用来完成将基类指针或者引用强制转换回派生类的指针或者引用,这样做可能会失败。
dynamic_cast运算符可以在执行期决定真正的类型。如果downcast是安全的(也就说,如果基类指针确实指向一个派生类对象)
这个运算符会传回适当转型过的指针。如果downcast不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个
派生类对象)。---摘自《深度探索C++对象模型》。

-----------------------------------------------------------------------------------------------

(4)reinterpret_cast    主要用来在类型无关的变量之间进行强制类型转换
该运算符的用法为:
reinterpret_cast<type_id>(expression)。
eg:
  int *int_ptr=new int ;
  char *ch_ptr=reinterpret_cast<char *>(int_ptr);
该转换将一个int型的指针强制转换为一个char类型的指针。并可以如下
编写string str(ch_ptr);//编译器并不会报错,但是会有运行时bug。
因为ch_ptr指向的内存中存储的是一个整型int变量。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>

using namespace std;

int main()
{
  int a[]={20011};
  char *d=reinterpret_cast<char*>(a);
  string str(d);
  cout<<a[0]<<endl;
  cout<<str<<endl;
    return 0;
}
程序输出:
20011
+N
可见编译器对20011的二进制位模式重新进行了解释。

eg:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>

using namespace std;

int main()
{
  int a[]={2};
  double *d=reinterpret_cast<double *>(a);
  cout<<a[0]<<endl;
  cout<<*d<<endl;
    return 0;
}
程序输出为:
2
4.85773e-270
可见编译器将2的二进制转换成了一个浮点数了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值