C++类型转换之dynamic_cast

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就像一个姑娘,为了躲避仇家,化妆为男性,一路蒙混过关,但不管怎么样,危机关头还是表现出女性的害怕,改变不了。而强制转换,就是去泰国做手术,变性,完完全全改变了原来的特征。
C++还有reinterpret_cast类型、const_cast类型,,但是建议尽量不使用它们,就像你家里备有感冒药,却不把它当饭吃,仅当你真正需要时才使用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值