博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++强制类型转换
阅读量:6230 次
发布时间:2019-06-21

本文共 4247 字,大约阅读时间需要 14 分钟。

C强制转换

  C语言中的强制转换主要用于普通数据类型、指针的强制转换,没有类型检查,转换不安全,语法为:

(type-id)expression//转换格式1type-id(expression)//转换格式2

  C++除了能使用c语言的强制类型转换外,还新增了四种强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要运用于继承关系类间的强制转化,语法为:

//静态转换static_cast
(expression)//动态转换dynamic_cast
(expression) //常量转换const_cast
(expression) //重新解释转换reinterpret_cast
(expression)

  其中new type为转换后的新类型,expression为旧类型

C++强制类型转换

1. static_cast 静态转换(编译时检查)

  static_cast静态转换相当于C语言中的强制转换,但不能实现普通指针数据(空指针除外)的强制转换,一般用于父类和子类指针、引用间的相互转换。

  ①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。不管是否发生多态,父子之间互转时,编译器都不会报错。

    进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;

    进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的,但是编译器不会报错。

  ②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

  ③把空指针转换成目标类型的空指针。

  ④把任何指针类型转换成空指针类型。

  ⑤可以对普通数据的const和non_const进行转换,但不能对普通数据取地址后的指针进行const添加和消去。

  ⑥无继承关系的自定义类型,不可转换,不支持类间交叉转换。

  注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性
1 class Person{ 2  3 }; 4  5 class Son :public Person{ 6  7 }; 8  9 class My{};10 11 void test02(){12     char a = 'c';13     int b = static_cast
(a);14 cout << b << endl;15 16 const char a0 = 'c';17 char b0 = static_cast
(a0);18 cout << b0 << endl;19 20 char a1 = 'c';21 const char b1 = static_cast
(a1);22 cout << b1 << endl;23 24 //static无法丢掉常量或其他类型限定符,只限于对常量地址的指针去const25 //const char a2 = 'c';26 //char *b2 = static_cast
(&a2);27 //cout << b2 << endl;28 29 30 //父类指针转为子类31 Person *p = NULL;32 Son *s = static_cast
(p);33 34 //子类指针转为父类35 Son *s0 = NULL;36 Person *p0 = static_cast
(s0);37 38 //My* my= static_cast
(p); 无继承关系的自定义数据类型不能相互转换39 40 //父类对象无法转为子类对象41 //Person p1;42 //Son s1 = static_cast
(p1);43 44 //子类对象可以赋值,初始化父类对象45 Son s2;46 Person p2 = static_cast
(s2);47 48 //父类引用转为子类49 Person p_ ;50 Person &p3 = p_;51 Son &s3 = static_cast
(p3);52 53 //子类引用转为父类54 Son s_;55 Son &s4 = s_;56 Person &p4 = static_cast
(s4);57 58 //空指针转化为目标类型的指针59 void *pPtr = NULL;60 int *iPtr = static_cast
(pPtr);61 62 //任何指针转化为空指针类型63 int *aInt = NULL;64 void *aVoid = static_cast
(aInt);65 66 //static_cast不能进行出void外的指针强制互转67 char *tmp = "abc";68 cout << tmp << endl;69 70 //cout << static_cast
(tmp) << endl;不能将char*型的数据转换为int*,但C语言强转可以71 cout << static_cast
(tmp) << endl;72 73 int *tmp_ = (int*)(tmp); 74 cout << static_cast
(tmp_) << endl;75 76 int *tmpInt = 0;77 cout << tmpInt << endl;78 cout << static_cast
(tmpInt) << endl;79 cout << static_cast
(tmpInt) << endl;//转为自身可以80 }

2.dynamic_cast 动态转换(运行时检查)

  动态转换的类型和操作数必须是完整类类型或空指针、空引用,说人话就是说,只能用于类间转换,支持类间交叉转换,不能操作普通数据

  主要用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换,

    ①进行上行转换(把派生类的指针或引用转换成基类表示)是安全的,允许转换;

    ②进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的,不允许转化,编译器会报错;

    ③发生多态时,允许互相转换。

    ④无继承关系的类之间也可以相互转换,类之间的交叉转换。

    ⑤如果dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常

3. const_cast 常量转换

  const_cast,用于修改类型的const或volatile属性,不能对非指针或非引用的变量添加或移除const。

1 const int g = 20; 2 //int h = const_cast
(g); //不允许对普通数据进行操作 3 int *h = const_cast
(&g);//去掉const常量const属性 4 5 const int g0 = 20; 6 const int &g2 = g0; 7 int &h = const_cast
(g0);//去掉const引用const属性 8 int &h2 = const_cast
(g2);//去掉const引用const属性 9 10 const char *g1 = "hello";11 char *h = const_cast
(g1);//去掉const指针const属性

4.reinterpret_cast 重新解释转换

  最鸡肋的转换函数,可以将任意类型转换为任意类型,因此非常不安全。只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。

  另外,static_cast和reinterpret_cast的区别主要在于多重继承,比如

1 class A { 2     public: 3     int m_a; 4 }; 5   6 class B { 7     public: 8     int m_b; 9 };10  11 class C : public A, public B {};12 13 void test(){14     C c;15     printf("%p, %p, %p", &c, reinterpret_cast
(&c), static_cast
(&c));16 }

  前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换

 

转载于:https://www.cnblogs.com/qinguoyi/p/10303912.html

你可能感兴趣的文章
Android:MVC模式(上)
查看>>
vi编辑器的使用(2)
查看>>
bootstrap-.col-md-* 栅格类
查看>>
解释器模式-类行为型
查看>>
虚拟现实强势“入侵”游戏盛典China Joy
查看>>
bootstrap-分页导航(翻页分页导航)
查看>>
innobackupex备份mysql数据库
查看>>
HTML5新标签的兼容性处理
查看>>
iptables学习笔记
查看>>
jQuery中的$(window)与$(document)的用法区别
查看>>
java中多种写文件方式的效率对比实验
查看>>
Cisco 2960 配置
查看>>
阿里大鱼数据库存储方案
查看>>
if判断的几种用法
查看>>
mysql安装与初始配置
查看>>
su命令
查看>>
linux 安装nginx
查看>>
建议把.CSV的默认打开方式改成任意一个文本 编辑器,系统自带的记事本就是个不错的选择...
查看>>
js 邮箱、11位手机正则
查看>>
使用Vim插件管理器Vundle
查看>>