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操 ...
随机推荐
- unity面试题二
1.以下哪一个选项不属于Unity引擎所支持的视频格式文件(D) A.后缀为mov的文件 B.后缀为mpg的文件 C.后缀为avi的文件 D.后缀为swf的文件 2.Unity引擎使用的是左手坐标系还 ...
- ElasticSearch搜索引擎安装配置拼音插件pinyin
近几篇ElasticSearch系列: 1.阿里云服务器Linux系统安装配置ElasticSearch搜索引擎 2.Linux系统中ElasticSearch搜索引擎安装配置Head插件 3.Ela ...
- python基础之变量和简单数据类型
1.1 变量的命名和使用规范 变量名可以包含数字.字母.下划线,但是不能以数字开头. 变量名不能包含空格,可使用下划线来分割其中的单词. 不要将Python关键字和函数名用作变量名. 变量名应既简短又 ...
- TPO-10 C2 Return a literature book
TPO-10 C2 Return a literature book 第 1 段 1.Listen to a conversation between a student and an employe ...
- python学习笔记02 --------------基础数据类型
python的基本数据类型: 1.基本数据 1.1. 数字类型 1.1.1 整数 int int() #将括号内内容转化为整数类型. 1.1.2 浮点数 float 1.1.3 复 ...
- TW实习日记:第20-21天
为什么上周五没写呢,因为上周五一直在熟悉业务流程...根本不会写一些复杂的业务代码,因为没有业务流程图!!!在学校的上需求分析和UML建模课的时候,还有软件工程课的时候,想着这都什么鬼啊,听来干嘛,写 ...
- NO.01---今天聊聊Vuex的简单入门
作为一款个人认为非常牛x的框架,个人使用起来得心应手,所以近期就记录一下这款框架吧. 首先说一说 Vuex 是什么? 官方给出的解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它 ...
- JDBC中使用Properties类及配置文件的操作
同时发布于:https://blog.csdn.net/Activity_Time/article/details/81149710 一.properties配置文件 开发中获得连接的4个参数(驱动. ...
- spark操作数据库的几种方法
一.使用jdbcRDD的接口: SparkConf conf = new SparkConf(); conf.setAppName("Simple Application").se ...
- LeetCode 98——验证二叉搜索树
1. 题目 2. 解答 2.1. 方法一 我们初始化根节点的范围为长整形数据的最小最大值 \([LONG\_MIN,LONG\_MAX]\),则其左子节点的取值范围为 \([LONG\_MIN,根节点 ...