c++提供了四种新的cast机制,分别为static_cast, const_cast, dynamic_cast和reinterpret_cast。虽然也支持c中使用一对圆括号来cast,但是由于c++与c最大的区别是c++增加了类的概念,因此在子类与父类之间进行cast的时候,使用c的cast方式是无法保证其正确性的,因此c++提供了新的cast机制(虽然比较丑陋而且需要敲打更多的code,但是提供了安全性):dynamic_cast。
对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。因此可以用来在运行期间进行类型判断。如下述演示代码。
class CShape{...}
class CCircle:public CShape{...}
class CRectangle: public CShape{...}
CShape * pShape;
... //do something
if (dynamic_cast<CCircle * > (pShape))
{
//process the Circle object
}
else if (dynamic_cast<CRectangle * > (pShape))
{
//process the Rectangle object
}
else
{
//error, just shape object
}
如下面代码所示,将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理,即会作一定的判断。由于这会用到RTTI技术,因此需要启动“运行时类型信息”这一选项,而在VC.net 2003中默认是关闭的,所以需要人为的启动这一选项,如图1所示。否则编译器会报下面的警告:
warning C4541: “dynamic_cast”用在了带 /GR- 的多态类型“CBasic”上;可能导致不可预知的行为
从而导致程序在运行时发生异常。
但是dynamic_cast在将父类cast到子类时,父类必须要有虚函数。例如在图1中的代码中将CBasic类中的test函数不定义成virtual时,编译器会报错:
error C2683: dynamic_cast : “CBasic”不是多态类型
这是由于有了多态后,将子类对象赋值给父类对象才有意义。这样子类与父类之间的cast才有意义。
当然如果使用dynamic_cast来直接将子类cast到父类(向上cast),那就无所谓了。即父类不需要一定有虚函数,也不需要开启“运行时类型信息”这一选项。
#include <iostream>
using namespace std;
class CBasic
{
public:
virtual int test()...{return 0;}
};
class CDerived : public CBasic
{
public:
virtual int test()...{ return 1;}
};
int main()
{
CBasic cBasic;
CDerived cDerived;
CBasic * pB1 = new CBasic;
CBasic * pB2 = new CDerived;
//dynamic cast failed, so pD1 is null.
CDerived * pD1 = dynamic_cast<CDerived * > (pB1);
//dynamic cast succeeded, so pD2 points to CDerived object
CDerived * pD2 = dynamic_cast<CDerived * > (pB2);
//dynamci cast failed, so throw an exception.
// CDerived & rD1 = dynamic_cast<CDerived &> (*pB1);
//dynamic cast succeeded, so rD2 references to CDerived object.
CDerived & rD2 = dynamic_cast<CDerived &> (*pB2);
return 0;
}
没有评论:
发表评论