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操 ...
随机推荐
- 卸载Oracle 11g
卸载oracle只需要执行deinstall.ba即可 运行.bat文件 按照提示步骤进行卸载 .bat文件所在目录需要手动删除,需要在程序管理器里面关掉Oracle的进程,在删除当前文件夹
- Net Core学习笔记
Net Core 官网:https://dotnet.github.io/ Net Core Api: https://docs.microsoft.com/en-us/dotnet/api/?vie ...
- .net MVC 图片水印,半透明
filter:alpha(opacity=50):这个是为IE6设的,可取值在0-100,其它三个0到1.-moz-opacity:0.5; 这个是为了支持一些老版本的Mozilla浏览器.-khtm ...
- 2019年猪年海报PSD模板-第四部分
14套精美猪年海报,免费猪年海报,下载地址:百度网盘,https://pan.baidu.com/s/1WUO4L5PHIHG5hAurv52_2A
- PLSQL集合类型
PLSQL集合类型 --联合数组(索引表) /* 用于存储某个数据类型的数据集合类型 .通过索引获得联合数组中得值 如下例子: */ DECLARE CURSOR cur_chars IS SEL ...
- 【白书训练指南】(UVa10755)Garbage Heap
先po代码,之后把我那几个不太明了的知识点讲讲,巩固以下.三维的扫描线算法想要掌握还真是有一定的难度的. 代码 #include <iostream> #include <cstri ...
- Appium的环境搭建和配置
Appium的环境搭建和配置 一.安装Nodejs 下载nodejs安装包(https://nodejs.org/en/download/)安装 下载后,双击安装文件,按提示来安装. 测试安装是否成功 ...
- Selenium(Python)页面对象+数据驱动测试框架
整个工程的目录结构: 常用方法类: class SeleniumMethod(object): # 封装Selenium常用方法 def __init__(self, driver): self.dr ...
- Python 多线程、进程、协程上手体验
浅谈 Python 多线程.进程.协程上手体验 前言:浅谈 Python 很多人都认为 Python 的多线程是垃圾(GIL 说这锅甩不掉啊~):本章节主要给你体验下 Python 的两个库 Thre ...
- 记一次Log4j2日志无法输出的 心酸史
问题描述:部分日志无法输出到日志文件中. 项目中的代码: @Resource private ConfigInfo configInfo; private static final Logger lo ...