您的位置:首页 > 编程语言 > C语言/C++

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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: