C++类型转换之dynamic_cast
2016-04-12 23:45
573 查看
C++提供了一种新的类型转换运算符,专门用于继承的情形,这种情形在c语言中不存在。
再说dynamic_cast之前,我想先说说static_cast
static_cast用于在相关类型的指针之间进行转换,还可以显示地执行标准数据类型的类型转换—这种转换原本将自动或隐式进行。用于指针时,static_cast实现了基本的编译阶段检查。确保指针被转换为相关类型。这改进了c风格类型转换,在c语言中,可将指向一个对象的指针转换为完全不相关的类型,而编译器不会报错。使用static_cast可将指针向上转换为基类类型,也可向下转换为派生类型。Base* pBase=new Derived(); Derived* pDerived=static_cast<Derived*>(pBase);
这段代码是没有什么问题的,如果是转化为无关的类指针,
CUnrelated pUnrelated=static_cast<CUnrelated*>(pBase);
然而,static_cast只验证指针类型是否相关,而不会执行任何运行阶段检查,因此我们可以使用static_cast编写如下代码,而编译器不会报错:
Base* pBase=new Base(); Derived* pderived=static_cast<Derived*>(pBase);
其中pDerived实际上指向一个不完整的Derived对象,因此它指向的对象实际上是Base()类型。由于static_cast只在编译阶段检查转换类型是否相关,而不执行运行阶段检查,因此pDerived->someDerivedFunction()能够通过编译,但在运行阶段可能会出意外。
使用dynamic_cast
顾名思义,与静态类型转换相反,动态类型在运行阶段执行类型转换,可检查dynamic_cast操作结果,以判断转换类型是否成功。语法如下:destination_type* pDest=dynamic_cast<class_type*)(pSource); if(pDest) //check for success of //the casting operation before using point pDest->CallFunc();
eg:
Derived* pDerived=dynamic_cast<Derived*>(pBase); if(pDerived) pDerived->callderivedClassFunction();
给定一个指向基类对象的指针,程序员可以使用dynamic_cast进行类型转换,并在使用指针前检查指针指向目标对象的类型。下面给一个完整的例子。
#include <iostream> using namespace std; class Fish { public: virtual void Swim() { cout << "Fish swims in water" << endl; } // base class should always have virtual destructor virtual ~Fish() {} }; class Tuna: public Fish { public: void Swim() { cout << "Tuna swims real fast in the sea" << endl; } void BecomeDinner() { cout << "Tuna became dinner in Sushi" << endl; } }; class Carp: public Fish { public: void Swim() { cout << "Carp swims real slow in the lake" << endl; } void Talk() { cout << "Carp talked crap" << endl; } }; void DetectFishType(Fish* InputFish) { Tuna* pIsTuna = dynamic_cast <Tuna*>(InputFish); if (pIsTuna) { cout << "Detected Tuna. Making Tuna dinner: " << endl; pIsTuna->BecomeDinner(); // calling Tuna::BecomeDinner } Carp* pIsCarp = dynamic_cast <Carp*>(InputFish); if(pIsCarp) { cout << "Detected Carp. Making carp talk: " << endl; pIsCarp->Talk(); // calling Carp::Talk } cout << "Verifying type using virtual Fish::Swim: " << endl; InputFish->Swim(); // calling virtual function Swim } int main() { Carp myLunch; Tuna myDinner; // Carp* MyCarp = &myLunch; // Fish* MyFish = MyCarp; // Carp* MyCarpAgain = MyFish; DetectFishType(&myDinner); cout << endl; DetectFishType(&myLunch); return 0; }
结果如下:
而如果不适用dynamic_cast来转换,使用强制转换,我们修改一处
void DetectFishType(Fish* InputFish) { Tuna* pIsTuna =(Tuna*)InputFish ;//dynamic_cast <Tuna*>(InputFish); if (pIsTuna) { cout << "Detected Tuna. Making Tuna dinner: " << endl; pIsTuna->BecomeDinner(); // calling Tuna::BecomeDinner }
我们发现,使用强制转换后,可以将pCarp*类型转换为pTuna*类型,有时候这是我们需要的,有时候是我们不需要的。采用强制转换,即便是pFish类型,也能满足if(pIsTuna)的判断,进而输出,而使用dynamic_cast
举个例子:dynamic_cast就像一个姑娘,为了躲避仇家,化妆为男性,一路蒙混过关,但不管怎么样,危机关头还是表现出女性的害怕,改变不了。而强制转换,就是去泰国做手术,变性,完完全全改变了原来的特征。
[b]C++还有reinterpret_cast类型、const_cast类型,,但是建议尽量不使用它们,就像你家里备有感冒药,却不把它当饭吃,仅当你真正需要时才使用。[/b]