理解C++ dynamic_cast

转载 2015年07月07日 21:40:58

在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与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:

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实现原理

dynamic_cast是一个操作符,查看

dynamic_cast详解

作为四个内部类型转换操作符之一的dynamic_cast和传统的C风格的强制类型转换有着巨大的差别。除了dynamic_cast以外的转换,其行为的都是在编译期就得以确定的,转换是否成功,并不依赖被转...

C++中static_cast和dynamic_cast强制类型转换

前言 说起C++中的继承、多态、虚函数等概念,可能很多同学都有所了解,但是要说真正熟知的同学可能就不是很多了。最近在编程过程中了解到C++类型的层次转换(这就涉及到了多态和继承的相关概率),通常C语言...

C++中深入理解dynamic_cast

dynamic_cast运算符的主要用途:将基类的指针或引用安全地转换成派生类的指针或引用,并用派生类的指针或引用调用非虚函数。如果是基类指针或引用调用的是虚函数无需转换就能在运行时调用派生类的虚函数...

C++ 中 dynamic_cast 使用(二)

首先,dynamic_cast依赖于RTTI信息,其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,这种检查不是语法上的,而是真实情况的检查。 ...

什么是网关

什么是网关标签: 网络网关是一种充当转换重任的计算机系统或设备。在使用不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信...

在ubuntu14.04编译protobuf-c for arm版本

摘要:protobuf-c,也就是Google Protocol Buffers针对c语言版本的实现,libprotobuf-c是使用纯c语言实现的encoding和decoding,如何通过交叉编译...

理解C++ dynamic_cast

理解C++ dynamic_cast

理解C++ dynamic_cast

在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynamic_cast函数用于动态转型...

理解C++ dynamic_cast

在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynamic_cast函数用于动态转型...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:理解C++ dynamic_cast
举报原因:
原因补充:

(最多只允许输入30个字)