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 = ;
char *q = static_cast<char*>(&a);
cout<<*q<<endl;
上述代码不能被编译通过,因为static_cast对于指针的转换,只能接受void*类型,上述&a依然是int型指针,不能通过编译。
代码2:
int a = ;
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 ;
} int main(void)
{
const int a = ;
func(a);
return ;
}
上述代码中,a是一个const变量,但在func函数中的形参需要一个int型变量。很显然,编译直接报错,因为实参与形参具有不同的类型。如何解决这个问题?这就需要引入const_cast进行类型转换
const_cast只能改变运算对象的底层const。即对于一个const对象,const_cast可以将其const限定移除。上述代码修改为:
int func(int *a)
{
return ;
} int main(void)
{
const int a = ;
int *p = const_cast<int*>(&a);
func(p);
}
这里将const的变量a的指针,强制类型转换为非const的指针,在func中传入指针变量,程序即可以成功编译。
这里就有一个疑问:如果可以const_cast将const变量转换为非const变量,是否意味着,可以对const变量进行修改?如果可以,那是不是违背了const关键字的初衷? 这里再看一个样例代码:
int main(void)
{
const int a = ;
const int *p = &a;
int *q = const_cast<int*>(p); cout<<&a<<endl;
cout<<p<<endl;
cout<<q<<endl; cout<<*q<<endl;
*q = ;
cout<<*p<<endl;
cout<<a<<endl;
return ;
}
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 = ;
char *q = reinterpret_cast<char*>(&a);
cout<<*q<<endl;
上述对于static_cast的使用,需要对&a转换为void*才能够进行,但使用reinterpret_cast则可以直接进行转换。reinterpret_cast本质上依赖于机器。
四、dynamic_cast
关于dynamic_cast,用法比较丰富,会再之后进行讨论。
结论:对于一条强制类型转换的语句,都应该反复斟酌是否能用其他方式来实现相同的目标,就算实在无法避免,也应用尽量限制类型转换值的作用域,并记录对相关类型的所有假定,这样可以减少错误发生的机会。
C++学习之路(八):关于C++提供的强制类型转换的更多相关文章
- zigbee学习之路(八):定时器1(中断)
一.前言 通过上次的实验,我们已经学会了定时器3的中断方式,这次,我们来看看定时器1通过中断怎么控制. 二.原理分析 定时器1的初始化跟前面提到的一样,也是要配置寄存器T1CTL,还要进行开中断的操作 ...
- IOS学习之路八(GCD与多线程)
GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操作的机制.它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务. GCD中的FIFO队列称为 ...
- Object-c学习之路八(NSArray(数组)遍历和排序)
今天学习了NSArray的遍历和排序,现在在这里做一下总结: 遍历现在实现了四中方法: 排序大概有三中方法:(代码中都有注释) 关于对象的排序还是以Student和Book为例 每个Student持有 ...
- 嵌入式Linux驱动学习之路(八)创建最小的根文件系统
busybox 在配置busybox,在是否选择要静态链接库时,在静态下,busybox中的工具不需要动态链接库,能够直接运行.而用户自己编写的程序如果需要动态链接库,还是依然需要有. 如果是动态链接 ...
- IOS7学习之路八(iOS 禁止屏幕旋转的方法)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { retu ...
- Java学习之路(八):Set
Set集合概述以及特点: set 是一个不包含重复元素的collection set只是一个接口,一般使用它的子类HashSet,LinkedHashSet,TreeSet HashSet 此类是Se ...
- python学习之路 八 :面向对象编程基础
本节重点 了解面向对象.面向过程的区别 掌握什么是类,什么是对象 掌握如何定义及使用类和对象 了解类与对象间的关系 掌握类属性和实例属性 掌握绑定方法 一.编程范式 编程即写程序or写代码 ...
- Linux学习之路(一)
导语: 早前为了方便日常开发,建立跟生产环境类型的环境的时候考虑使用docker作为模拟生产环境,结果没想到给自己的学习挖了一个大坑.其他关于docker容器技术的坑先不在这里赘述,有时间的话在其他文 ...
- 微软企业库5.0 学习之路——第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息
在介绍完企业库几个常用模块后,我今天要对企业库的配置文件进行处理,缘由是我打开web.config想进行一些配置的时候发现web.config已经变的异常的臃肿(大量的企业库配置信息充斥其中),所以决 ...
随机推荐
- Java中的日志——Java.util.logging、log4j、commons-logging
Java中给项目程序添加log主要有三种方式,一使用JDK中的java.util.logging包,一种是log4j,一种是commons-logging.其中log4j和commons-loggin ...
- 【】Python】异常处理try...except、raise
一.try...except 有时候我们写程序的时候,会出现一些错误或异常,导致程序终止.例如,做除法时,除数为0,会引起一个ZeroDivisionError 例子: 1 2 3 4 a=10 b= ...
- 【bzoj5108】[CodePlus2017]可做题 拆位+乱搞
题目描述 给出一个长度为 $m$ 的序列 $a$ ,编号为 $a_1\sim a_m$,其中 $n$ 个位置的数已经确定,剩下的位置的数可以任意指定.现在令 $b$ 表示 $a$ 的前缀异或和,求 $ ...
- shell脚本学习—条件测试和循环语句
条件测试 1. 条件测试:test [ 命令test或[可以测试一个条件是否成立,如果测试结果为真,则该命令的Exit Status为0,如果测试结果为假, 则命令的Exit Status为1(注意与 ...
- 最新发现:Object.defineProperty()让数组的length属性变成只读
将属性添加到对象, 或修改现有属性的特性---MSDN的解释. 语法 object.defineProperty(object, propertyname, descriptor) object: 必 ...
- BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...
- CentOS 转义字符
常用转义字符 反斜杠(\):使反斜杠后面的一个变量变为单纯的字符串. 单引号(''):转义其中所有的变量为单纯的字符串. 双引号(""):保留其中的变量属性,不进行转义处理. 反引 ...
- CentOS7 从查看、启动、停止服务说起systemctl
执行命令“systemctl status 服务名.service”可查看服务的运行状态,其中服务名后的.service 可以省略,这是CenOS7以后采用systemd作为初始化进程后产生的变化. ...
- URL 编码规则
规则: 1.将空格转换为加号(+) 2.对0-9.a-z.A-Z之间的字符保持不变 3.对于所有其他的字符,用这个字符的当前当前字符集编码在内存中的十六进制格式表示,并在每一个字节前加上一个百分号(% ...
- [COGS2652]秘术「天文密葬法」
description 题面 给个树,第\(i\)个点有两个权值\(a_i\)和\(b_i\),现在求一条长度为\(m\)的路径,使得\(\frac{\sum a_i}{\sum b_i}\)最小 d ...