C++中的四种转型操作符
在具体介绍C++中的四种转型操作符之前,我们先来说说旧式转型的缺点:
①它差点儿同意将不论什么类型转换为不论什么其它类型,这是十分拙劣的。假设每次转型都可以更精确地指明意图,则更好。
②旧式转型难以辨识。旧式转型的语法结构是由一对小括号加上一个对象名称组成。而小括号和对象名称在C++的不论什么地方都有可能被使用。
为解决C旧式转型的缺点,C++导入了4个新的转型操作符:static_cast、const_cast、dynamic_cast、reinterpret_cast。
以下我来一一分析这四种转型操作符。
1)static_cast
static_cast基本上拥有与C旧式转型同样的威力与意义,以及同样的限制。
比如。不可以利用static_cast将一个struct转型为int。或将一个double转型为pointer;这些都是C旧式转型动作原本就不可以完毕的任务。
static_cast甚至不可以移除表达式的常量性。
int a,b;
...
double c = static_cast<double>(a)/b;
2)const_cast
const_cast用来改变表达式中的常量性(constness)或变易性(volatileness)。使用const_cast,便是对人类(以及编译器)强调,通过这个转型操作符,我们唯一想改变的是某物的常量性或变易性。
假设将const_cast应用于上述以为的用途。那么转型动作会被拒绝。以下看一个样例:
class Widget{...};
class SpecialWidget:public Widget {...};
void update(SpecialWidget* psw);
SpecialWidget sw;//sw是个non-const对象
const SpecialWidget& csw = sw;//csw却是一个代表sw的reference。并视之为一个const对象
update(&csw);//错误!
不能讲const SpecialWidget*传给一个须要SpecialWidget*的函数
update(const_cast<SpecialWidget*>(&csw));//可!
&csw的常量性被去除了。也因此,csw(亦即sw)在此函数中可被更改。
update((SpecialWidget*)&csw);//情况同上,但使用的是较难辨识的c旧式转型语法
Widget* pw = new SpecialWidget;
update(pw);//错误!pw的类型是Widget*,但update()须要的却是SpecialWidget*。
update(const_cast<SpecialWidgt*>(pw));//错误!const_cast仅仅能用来影响常量性或变易性,无法进行继承体系的向下转型动作。
3)dynamic_cast
①dynamic_cast用来运行继承体系中”安全地向下转型或跨系转型动作“。
也就是说你能够利用dynamic_cast。将”指向base class objects的pointers或references“转型为”指向derived(或sibling base)class objects的pointers或references“,并得知转型是否成功。
假设转型失败,会以一个null指针(当转型对象是指针)或一个exception(当转型对象是reference)表现出来:
Widget* pw;
...
update(dynamic_cast<SpecialWidget*>(pw));//非常好,传给update()一个指针,指向pw所指的SpecialWidget----假设pw真的指向这种东西。否则传过去的将是一个null指针
void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));//非常好。传给updateViaRef()的是pw所指的SpecialWidget----假设pw真的指向这种东西;否则抛出一个exception
dynamic_cast仅仅能用来助你巡航于继承体系之下。它无法应用在缺乏虚函数的类型身上,也不能改变类型的常量性。
②dynamic_cast的第二个用途是找出被某对象占用的内存的起始点。比如:
class HeapTracked
{
public:
bool isOnheap() const;
private:
typedef const void* RawAddress;
static list<RawAddress> addresses;
};
bool HeapTracked::isOnheap() const
{
const void* rawAddress = dynamic_cast<const void*>(this);//取得一个指针,指向*this所占内存的起始处
list<RawAddress>::iterator it = find(addresses.begin(),addresses.end(),rawAddress);
return it != addresses.end();
}
凡涉及”多重继承或虚拟基类“的对象,会拥有多个地址,仅仅要简单地将指针”动态转型“为void*(或const void*或volatile void*或const volatile void*),便会获得一个指针,指向”原指针所指对象“的内存起始处。
只是,dynamic_cast仅仅适用于那种”所指对象至少有一个虚函数“的指针身上。
4)reinterpret_cast
这个操作符的转换结果差点儿总是与编译平台息息相关。所以reinterpret_cast不具移植性。
reinterpret_cast的最经常使用用途是转换”函数指针“类型。
如果有一个数组。存储的都是函数指针。有特定的类型:
typedef void (*FuncPtr)();//FuncPtr是个指针,指向某个函数。
FuncPtr funcPtrArray[10];//funcPtrArray是个数组,内有10个FuncPtrs。
如果因为某种原因,你希望将下面函数的一个指针放进funcPtrArray中:
int doSomething();
假设没有转型。不可能办到这一点,由于doSomething的类型与funcPtrArray所能接受的不同。
funcPtrArray内各函数指针所指函数的返回值是void,但doSomething的返回值却是int:
funPtrArray[0] = &doSomething;//错误!类型不正确
使用reinterpret_cast,能够强迫编译器了解你的意图。
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);
函数指针的转型动作并不具有移植性(C++不保证全部的函数指针都能以此方式又一次呈现),某些情况下这种转型可能会导致不对的结果,所以应该尽量避免将函数指针转型。
假设编译器尚未支持这些新式转型动作,也能够使用传统转型方式代替static_cast、const_cast和reinterpret_cast。甚至能够利用宏来仿真这些新语法。
#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define const_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
至于dynamic_cast,也可回头使用旧式的C型语法。或者定义一个宏。可是它们不可能告诉你转型是否成功。
C++中的四种转型操作符的更多相关文章
- [转]C++四种cast操作符
http://blog.csdn.net/starryheavens/article/details/4617637 C 风格(C-style)强制转型如下: (T) expression 或 T(e ...
- C++四种cast操作符
C 风格(C-style)强制转型如下: (T) expression 或 T(expression) //函数风格(Function-style) 两种形式之间没有本质上的不同. 对于具有转换的简 ...
- 对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
一. AES对称加密: AES加密 分组 二. 分组密码的填充 分组密码的填充 e.g.: PKCS#5填充方式 三. 流密码: 四. 分组密码加密中的四种模式: 3.1 ECB模式 优点: 1. ...
- JAVA基础学习之throws和throw的区别、Java中的四种权限、多线程的使用等(2)
1.throws和throw的区别 throws使用在函数外,是编译时的异常,throw使用在函数内,是运行时的异常 使用方法 public int method(int[] arr) throws ...
- Activity中的四种启动模式
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...
- JAVA中的四种引用以及ReferenceQueue和WeakHashMap的使用示例
简介: 本文主要介绍JAVA中的四种引用: StrongReference(强引用).SoftReferenc(软引用).WeakReferenc(弱引用).PhantomReference(虚引用) ...
- C语言_了解一下C语言中的四种存储类别
C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言. C语言中的四种存储类别:auto ...
- Java中的四种引用
引用定义 实际上,Java中存在四种引用,它们由强到弱依次是:强引用.软引用.弱引用.虚引用.下面我们简单介绍下这四种引用: 强引用(Strong Reference):通常我们通过new来创建一个新 ...
- JavaScript确定一个字符串是否包含在另一个字符串中的四种方法
一.indexOf() 1.定义 indexOf()方法返回String对象第一次出现指定字符串的索引,若未找到指定值,返回-1.(数组同一个概念) 2.语法 str.indexOf(searchVa ...
随机推荐
- div中实现居中
今天纠结了大半天的居中,把学到的先记录下来,还没完全弄清楚,发现网上原创的技术贴并不算多,大多都是相互转载.(ps.先安利一个大神的帖集,昨天才发现的,内容丰富,语言,呃...很幽默,一般都是图文并茂 ...
- 《CSS网站布局实录》学习笔记(二)
第二章 XHTML与CSS基础 2.1 XHTML基础 XHTML是网页代码的核心内容,标准XHTML代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD ...
- Hadoop参数优化
dfs.block.size 决定HDFS文件block数量的多少(文件个数),它会间接的影响Job Tracker的调度和内存的占用(更影响内存的使用), mapred.map.tasks.spec ...
- Fiddler 网页采集抓包利器
最近这段时间,网页采集方面的工作做得比较多.用curl技术开发了一个微信文章聚合类产品,把抓取到的数据转换成json格式,并在android端调用json数据接口加以显示:基于weiphp做了一个掌上 ...
- Qt5-控件-QMenu,QMenuBar-菜单栏详解-菜单热键-菜单校验功能
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QMenu> #inclu ...
- Y - Design T-Shirt(第二季水)
Description Soon after he decided to design a T-shirt for our Algorithm Board on Free-City BBS, XKA ...
- 前端要怎么学createjs!!!???
前端想做js开发,可以.但是思维要变通,思维要重塑.为啥?因为被div+css坑的有点深.这些都是我自己总结的,不知道其他人是不是这样. 在我看来div+css算是开发吗?肯定不是,这些东西有难的东西 ...
- 企业管理系统开发笔记(4)---后台登录_MVC过滤器
在asp.net时代,我们通常需要在后台的每个页面进行判断用户是否登录的状态,不管是通过session还是通过windows身份验证还是表单验证方式等等方法来对用户登录进行判断跳转.但是在mvc时代, ...
- The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. (关于jdbc)
The last packet sent successfully to the server was milliseconds ago. The driver has not received an ...
- Web之CSS开发技巧: CSS 居中大全
<center> text-align:center 在父容器里水平居中 inline 文字,或 inline 元素 vertical-align:middle 垂直居中 inline 文 ...