在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynamic_cast函数用于动态转型。相比C风格的强制类型转换和C++ reinterpret_cast,dynamic_cast提供了类型安全检查,是一种基于能力查询(Capability Query)的转换,所以在多态类型间进行转换更提倡采用dynamic_cast。本文主要介绍dynamic_cast的意义,用法和注意事项。

基本用法

dynamic_cast可以获取目标对象的引用或指针:

T1 obj;

T2* pObj = dynamic_cast<T2*>(&obj);//转换为T2指针,失败返回NULL

T2& refObj = dynamic_cast<T2&>(obj);//转换为T2引用,失败抛出bad_cast异常

多态类型

在使用时需要注意:被转换对象obj的类型T1必须是多态类型,即T1必须公有继承自其它类,或者T1拥有虚函数(继承或自定义)。若T1为非多态类型,使用dynamic_cast会报编译错误。下面的例子说明了哪些类属于多态类型,哪些类不是:

//A为非多态类型

class A{

};

//B为多态类型

class B{

public: virtual ~B(){}

};

//D为多态类型

class D: public A{

};

//E为非多态类型

class E : private A{

};

//F为多态类型

class F : private B{

}

横向转型

在多态类型间转换,分为3种类型:

1.子类向基类的向上转型(Up Cast)

2.基类向子类的向下转型(Down Cast)

3.横向转型(Cross Cast)

向上转型是多态的基础,需不要借助任何特殊的方法,只需用将子类的指针或引用赋给基类的指针或引用即可,当然dynamic_cast也支持向上转型,而其总是肯定成功的。而对于向下转型和横向转型来讲,其实对于dynamic_cast并没有任何区别,它们都属于能力查询。为了理解方便,我们不妨把dynamic_cast视为cross cast:

class Shape {

public: virtual ~Shape();

virtual void draw() const = 0;

};

class Rollable {

public: virtual ~Rollable();

virtual void roll() = 0;

};

class Circle : public Shape, public Rollable {

void draw() const;

void roll();

};

class Square : public Shape {

void draw() const;

};

//横向转型失败

Shape *pShape1 = new Square();

Rollable *pRollable1 = dynamic_cast<Rollable*>(pShape2);//pRollable为NULL

//横向转型成功

Shape *pShape2 = new Circle();

Rollable *pRollable2 = dynamic_cast<Rollable*>(pShape2);//pRollable不为NULL

指针比较

接上面的例子,在我的机器上pShape2和pRollable2的值(所指向的地址)分别为:

pShape2: 0x0039A294, pRollable2:0x0039A290

说明dynamic_cast在进行转型的时候对不同多态类型设置了不同的偏移量。接下来的问题是

pRollable2 == pShape2

这个表达式应该返回什么呢?答案是:1,即指针比较相等。也许从C语言转到C++的朋友可能会感到困惑,因为在C语言中指针的比较只是值比较而已。显然,对于多态类型,C++编译器为==运算符做了更多的幕后工作来保证指针比较注重对象的同一性而非指针的值。至于实现细节涉及到C++对象模型,这是我还不甚熟悉的内容,故本文不再深入。

参考

C++ Common Knowledge Item27,28

C++ Typecasting

文中若有错误和不足,欢迎各位批评指正!

理解C++ dynamic_cast相关推荐

  1. When should static_cast, dynamic_cast and reinterpret_cast be used?

    这是我偶然在 http://stackoverflow.com/questions/ 网页上发现的一个问题(类似博客园的博问),问题主要是关于询问应该怎样使用,以及何时使用C++里面的这几种类型转换操 ...

  2. C++多态中虚函数的深入理解

    c++中动态多态性是通过虚函数来实现的.静态多态性是通过函数的重载来实现的,在程序运行前的一种早绑定,动态多态性则是程序运行过程中的一种后绑定.根据下面的例子进行说明. #include <io ...

  3. 【C++ 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 )

    文章目录 I . const_cast 转换操作符 II . static_cast 转换操作符 III . dynamic_cast 转换操作符 IV . reinterpret_cast 转换操作 ...

  4. 类型转换操作符:static_cast, dynamic_cast, const_cast, reinterpret_cast.

    呵呵,今天来好好看看着几个转换操作符的用法.以前老是看着眼熟,但是用着手生.今天决定搞定这些个东西. 在C语言中类型转换有几种方式: 1.      (expression). 在表达式外边加括号,由 ...

  5. static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较

    转载于:http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html 隐式转换(implicit conversion) s ...

  6. 深入理解C++内存管理

    深入理解C++内存管理 一文了解所有C++内存的问题 AlexCool 目录 一  C++内存模型 二  C++对象内存模型 三 C++程序运行内存空间模型 四  C++栈内存空间模型 五 C++堆内 ...

  7. C++四种强制类型转换 dynamic_cast,const_cast,static_cast,reinterpret_cast

    综述 dynamic_cast  用于多态类型的转换 static_cast 用于非多态类型的转换 const_cast  用于删除 const.volatile 和 __unaligned 特性 r ...

  8. 类型转换static_cast,dynamic_cast,const_cast,reinterpret_cast等

    一.隐式类型转换 系统自动进行,不需要程序开发人员介入. int m = 3 +45.6; //把小数部分截掉,也属于隐式类型转换的一种行为. doublen = 3 +45.6; 二.显示类型转换( ...

  9. C++类型转换运算符 static_cast,dynamic_cast,reinterpret_cast,const_cast

    类型转换是一种让程序猿可以临时或永久性改变编译器对对象的解释机制.可改变对象解释方式的运算符称为类型转换运算符. 为何须要进行类型转换 通常为了实现使用不同环境的个人和厂商编写的模块可以相互调用和协作 ...

最新文章

  1. 什么叫系统的可扩展性?
  2. python链表的创建_Python——新建链表
  3. pam_mysql模块安装
  4. 大型网站HTTPS 实践(一)| HTTPS 协议和原理
  5. Windows 下安装 Redis 1
  6. 程序设计导引【总述】
  7. 易编远航第三期第3期第4套-游戏大厅脚本开发集合
  8. maven 常用命令
  9. 数电技术基础大恶补04:CMOS门电路
  10. 中华传统文化网页作业报告
  11. 北京-地点-文创-南锣鼓巷:南锣鼓巷
  12. c软件查表获得电量代码_energy.c 源代码在线查看 - 基于单片机的多费率电能表源程序 资源下载 虫虫电子下载站...
  13. 建模实训报告总结_实验报告总结(15篇)
  14. Centos版Linux 一些常用操作命令 收集
  15. google 一个天生的在线超速代理。(刷票首选)
  16. 一张图说明softmax layer是什么
  17. 关闭jupyter notebook报错
  18. 李宏毅nlp学习笔记10:QA(Question answering)
  19. 会议邀请〡第六届全国高校电子信息类课程教学研讨会邀请函
  20. 去除IDEA报黄色/灰色的重复代码的下划波浪线

热门文章

  1. 西瓜书+实战+吴恩达机器学习(二一)概率图模型之贝叶斯网络
  2. 《Deep Learning》笔记
  3. 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析
  4. php冒泡排序的用途,浅谈php冒泡排序
  5. Layui表单账号注册校验密码是否一致
  6. Linux下autoconf与automake
  7. [Teamcenter 2007 开发系列] 整合Extjs 展现页面组件
  8. 利用高级筛选功能巧妙删除Excel的重复记录
  9. 一杯水怎么测试_怎么测家里自然水的水质情况?
  10. 发外链网站服务器瘫痪,哪些操作可以导致网站接入瘫痪 - 搜外SEO问答