C++中的显示类型转换
本文参考了《C++ Primer(中文 第5版)》、《王道程序员求职宝典》以及网上相关博客,结合自己的理解写成。个人水平有限,若有错误欢迎指出。
C++中显示转换也成为强制类型转换(cast),有四种:static_cast、dynamic_cast、const_cast、reinterpret_cast。命名的强制类型转换符号一般形式如下:
cast_name<type>(expression);
以下分别介绍
一、static_cast
任何具有明确定义的类型转换,只要不包含底层const都可以使用static_cast。好吧这句话我不是很懂,换句话:编译器隐式执行的任何类型转换都可以由static_cast显示完成。也就是说,两类型之间可以发生隐式的转换,就可以用static_cast显示转换,有点意思。但要知道的是C++基本类型的指针之间不含有隐式转换(void*除外、const的有些也是可以的),需要显示转换。什么意思?如下:
double d=3.14;
int i=d; //编译器的隐式转换,等价于下面这条语句
int i=static_cast<int>(d); /*指针之间的转换*/
char str[]="good";
char *ptr=str;
int *p=static_cast<int *>(ptr); //编译错误,两者之间的转换要显式,如下 int *p=(int *)(ptr);
仅当类型之间可隐式转换时(除类层次见的下行转换以外),static_cast的转换才是合法的,否则将出错。(基类指针或引用转换成子类指针或引用为下行转换)
类层次间的下行转换不能通过隐式转换完成,但是可以通过static_cast完成,但是由于没有动态类型检查,所以是不安全的。(至于这个不安全,我们会在dynamic_cast中具体说)。
class Base{};
class child:public Base{};
Base b;
child c;
c=static_cast<child *>(b); //下行转换,正确;
c=b; //编译错误
二、const_cast
只用使用const_cast才能将const性质转换掉。在这种情况下,试图使用其他三种形式的强制转换都会导致编译时的错误。类似地,除了添加或者删除const特性,用const_cast符来执行其他任何类型转换,都会引起编译错误。
const double val=3.14;
double *ptr=NULL; /*为了使ptr指向val,使用const_cast*/
ptr=const_cast<double *>(&val);
三、reinterpret_cast
从语法上看,这个操作符仅用于指针类型的转换(返回值是指针)。它用来将一个类型指针转换为另一个类型指针,它只需在编译时重新解释指针的类型。这个操作符基本不考虑转换类型之间是否是相关的。(参见:红心地瓜的博客和野男孩的博客)。
int *ip=NULL;
char *pc=reinterpret_cast<char *>(ip); /*注:必须牢记pc所指的真实对象是一个int而非字符,如果把pc当成普通的字符指针使用
*就可能在运行时发生错误*/
在《C++ Primer(中文 第五版 )》指出reinterpret_cast很危险,不建议使用。
四、dynamic_cast
该运算符把expression转换成type类型的对象。type必须是类型的指针、类的引用或者void*。type和expression的形式要对应,什么意思了?如:type是指针类型,那么expression也必须是一个指针。
与其他强制类型转换不同,dynamic_cast设计运行时类型检查。dynamic_cast运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表,故对没有不函数表的类使用会导致dynamic_cast编译错误。
另外,若绑定到引用或指针的对象类型不是目标类型,则dynamic_cast会失败(这点下面细说)。若转换到指针的失败,dynamic_cast的结果是0值,若转换到引用类型的失败,则抛出一个bad_cast类型的异常。
dynamic_cast主要符主要用于类层次间的上行转换和下行转换。
1、在类层次间上行转换时,dynamic_cast和static_cast的效果一样。因为在公有继承方式(保护继承、私有继承,不能隐式转换)下,派生类的对象/对象指针/对象引用可以赋值给基类的对象/对象指针/对象引用(发生隐式转换),反过来则不行。
2、若发生下行转换是安全的,也就是,如果基类指针或者引用的确指向一个派生类对象,这个运算符会传回转型过的指针,若不安全,则会传回空指针。
针对下行转换,换句话说:向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。
class Base
{
public:
Base():b() {}
virtual void foo() {}
int b;
}; class Derived:public Base
{
public:
Derived():d() {}
int d;
}; void func(Base *p)
{
Derived *pd1=static_cast<Derived *>(p); //语句1
cout<<pd1->b<<endl;
cout<<pd1->d<<endl;
Derived *pd2=dynamic_cast<Derived *>(p); //语句2
cout<<pd2->b<<endl;
cout<<pd2->d<<endl;
}
1)若调用函数func的实参p指向一个Derived类型的对象,即
Base *p=new Derived;
func(p);
则pd1和pd2是一样的,并且对这两个指针执行 Derived类的任何操作都是安全的,语句1和2都是输出1、2;
2)若p指向的是一个Base类型的对象,即
Base *p=new Base;
func(p);
那么pd1指向Base对象的地址,对它进行Derived类型的操作将是不安全的(如访问d),输出d的值时,将会是一个垃圾值;而pd2将是一个空指针,对空指针进行操作,将会发生异常。
Ref:
http://www.cnblogs.com/carsonzhu/p/5251012.html
C++中的显示类型转换的更多相关文章
- C语言中强制数据类型转换(转)
原文地址不详 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0-255(有些 ...
- 【转载】VC++中的图像类型转换--使用开源CxImage类库
一.CxImage类库简介 这只是翻译了CxImage开源项目主页上的部分简介及简单使用. CxImage类库是一个优秀的图像操作类库.它可以快捷地存取.显示.转换各种图像.有的读者可能说,有那么多优 ...
- C#将image中的显示的图片转换成二进制
原文:C#将image中的显示的图片转换成二进制 1.将Image图像文件存入到数据库中 我们知道数据库里的Image类型的数据是"二进制数据",因此必须将图像文件转换成字节数组才 ...
- Solidity中的基本类型转换
Solidity中的基本类型转换(十四)|入门系列 2017/4/29 posted in Solidity入门系列 点击查看原文,获得优化的排版. 隐式转换 如果一个运算符能支持不同类型.编译器会隐 ...
- 详细理解javascript中的强制类型转换
将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况:隐式的情况称为强制类型转换,JavaScript 中的强制类型转换总是返回标量基本类型值,如字符串.数字和布尔值. 如何理解: 类型转换 ...
- Struts2中的数据类型转换
Struts2对数据的类型转换 一.Struts2中自带类型转换拦截器 Struts2内部提供了大量转换器,用来完成数据类型转换的问题,有如下 * boolean 和 Boolean * char和 ...
- 关于Java中的基本数据类型转换
Java中的基本类型有四种,其中整型分为byte.short.int.long,浮点型分为float.double,字符型char,布尔型boolean.8种类型的级别由低到高byte->sho ...
- Visual Studio 2010 起始页中 不显示最近使用的项目问题,解决办法
最近新装了vs2010,发现打开vs2010 后 起始页面中的最近使用的栏目中 并未显示最近加载的项目 解决办法如下: 运行 regedit 打开下面的键值: HKEY_CURRENT_USER/So ...
- [转]C++中四种类型转换符的总结
C++中四种类型转换符的总结 一.reinterpret_cast用法:reinpreter_cast<type-id> (expression) reinterpret_cast操 ...
随机推荐
- libevent学习三(Getting an event_base)
1.一个event_base持有了一系列的事件,并监控和决定哪些事件需要激活, 2.每一个event_base背后都有一个支持其工作的方法(诸如select,poll,epoll,kquene...) ...
- unity3d 计时功能舒爽解决方案
上次也写了一篇计时功能的博客 今天这篇文章和上次的文章实现思路不一样,结果一样 上篇文章地址:http://www.cnblogs.com/shenggege/p/4251123.html 思路决定一 ...
- 巧用浏览器F12调试器定位系统前后端bug
做测试的小伙伴可能用过httpwatch,firebug,fiddler,charles等抓包(数据包)工具,但实际上除了这些还有一个简单实用并的抓包工具,那就是浏览器的F12调试器. httpwat ...
- Angualr6访问API
参照 草根专栏- ASP.NET Core + Ng6 实战: https://v.qq.com/x/page/a0769armuui.html 1.environment.ts 添加apiUrlBa ...
- Java进阶知识点:服务端高并发的基石 - NIO与Reactor AIO与Proactor
一.背景 要提升服务器的并发处理能力,通常有两大方向的思路. 1.系统架构层面.比如负载均衡.多级缓存.单元化部署等等. 2.单节点优化层面.比如修复代码级别的性能Bug.JVM参数调优.IO优化等等 ...
- Python实现个性化推荐二
基于内容的推荐引擎是怎么工作的 基于内容的推荐系统,正如你的朋友和同事预期的那样,会考虑商品的实际属性,比如商品描述,商品名,价格等等.如果你以前从没接触过推荐系统,然后现在有人拿枪指着你的头,强迫你 ...
- NMAP-端口扫描
1.时序选项 -T0 -> -T5 速度变快,但是准确性下降,nmap默认是T3 2.指定端口 3.扫描指定TCP和UDP端口 4.快速扫描常见100个端口 5.扫描常见的n的端口 6.TCP ...
- 2018-8-29安装Jitamin过程实录
2018-8-29安装Jitamin过程实录 新建 模板 小书匠 欢迎走进zozo的学习之旅. 简介 安装 nginx + php + mysql 安装composer 安装Jitamin 简介 在考 ...
- 11.24Daily Scrum(4)
人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.1007 实现视频浏览的功能 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.1008 实现视频浏 ...
- android入门 — ListView
ListView主要是用来解决大量数据展示的问题,它的用途很广泛,几乎所有的app都会用到,比如说知乎.今日头条.微博.通讯录等. ListView允许用户通过上下滑动的方式将屏幕外的数据滚动到屏幕中 ...