type_cast、static_cast和dynamic_cast

一、type_cast

type_cast主要作用是在继承树的各类之间作 "逆 "转换--- "由基类转换成派生类 ".
而所谓的 "正 "转换--- "由派生类转换成基类 ",是隐含转换,不需要type_cast.

1. "由派生类转换成基类 "---好理解,   运用虚函数实现多态时,经常用.

===================    虚函数    =====================  
#include   
< iostream >  
using     namespace    std; 

class    Base   { 
public
    
virtual     void    fun()   { 
    cout   
<   <     " Base::fun  "     <   <    endl; 
    } 
}; 

class    Drive   :    public    Base   { 
public
    
void    fun()   { 
    cout   
<   <     " Drive::fun  "     <   <    endl; 
    } 
}; 

int    main()   { 
    Base   
* pBase; 
    Drive   
* pDrive    =     new    Drive; 

    
//    
    pBase    =    pDrive;  <======     " 由派生类转换成基类  "     --- 正转换 
    pBase
->  fun();  <======    调用Drive::fun 

    
return     0

2.而 " 由基类转换成派生类 "的 "逆 "转换什么时候用到呢?
    ------- 那就是要实现模版形式的多态时!!

#include    < iostream >  
using     namespace    std; 

template   
< typename   T >  
class    Base   { 
public
    
void    fun()   { 
        cout   
<   <     " Base::fun  "     <   <    endl; 
    } 

    
void    doSomething()   { 
    T
*    pT    =    static_cast  < T *>  ( this );  <==     " 由基类转换成派生类  " 的  " 逆  " 转换 
    pT
->  fun(); 
    } 
}; 

class    Drive   :    public    Base  < Drive >    { 
public
    
void    fun()   { 
    cout   
<   <     " Drive::fun  "     <   <    endl; 
    } 
}; 

int    main()   { 
    Drive   obj; 
    obj.doSomething(); 

    
return     0

另外需要注意的是,   type_cast对指针地址的影响

1.单继承时,不管怎么在类型之间type_cast转换,指针的地址不变.
2.而对多继承时,类型之间type_cast转换,指针的地址是可能变化的.
class   Drive   :   public   IBase1,   public   IBase2   {
}

Drive   *pDrive   =   new   Drive;

//   "由派生类转换成基类 "
IBase1   *pIBase1   =   pDrive;         //   pIBase1   =   pDrive
IBase1   *pIBase2   =   pDrive;         //   pIBase2   !=   pDrive   ==   地址改变

// "由基类转换成派生类 "的 "逆 "转换
pDrive   =   type_cast <Drive   *> pIBase1; //pDrive   =   pIBase1
pDrive   =   type_cast <Drive   *> pIBase2;   //pDrive   !=   pIBase2

二、static_cast与reinterpret_cast
static_cast必须是对在具有继承关系的类型之间转换.
而对reinterpret_cast,   互相转换的类型之间可以没有继承关系.
就像它名字一样-----对转换后的内容 "重新解释 ".
有点强制转换的意思!:)

对reinterpret_cast,   在任何情况下reinterpret_cast转换,指针的地址不变.

pIBase1   =   reinterpret_cast <IBase1   *> pIBase2;

pIBase1与pIBase2地址一样,但经reinterpret_cast "强制 "转换后,pIBase1调用的IBase1的方法.
----很危险!

那什么情况下会用到reinterpret_cast呢?

三、dynamic_cast主要是对指针或引用进行转换.
它检查被转换方的数据完整性.
因此dynamic_cast对从派生类向基类转换总是成功的.

比如:
class   CBase   {   };
class   CDerived:   public   CBase   {   };

CBase   b;   CBase*   pb;
CDerived   d;   CDerived*   pd;

pb   =   dynamic_cast <CBase*> (&d);           //   ok:   derived-to-base
pd   =   dynamic_cast <CDerived*> (&b);     //   wrong:   dynamic_cast不能将基类向派生类转换

但dynamic_cast可以对虚类作 "基类向派生类转换 ".但必须runtime检查 "被转换方的数据完整性 ".

例如:
class   CBase   {   virtual   void   dummy()   {}   };
class   CDerived:   public   CBase   {   int   a;   };

int   main   ()   {
    try   {
        CBase   *   pba   =   new   CDerived;
        CBase   *   pbb   =   new   CBase;
        CDerived   *   pd;

        pd   =   dynamic_cast <CDerived*> (pba);
        if   (pd==0)   cout   < <   "Null   pointer   on   first   type-cast "   < <   endl;

        pd   =   dynamic_cast <CDerived*> (pbb);
        if   (pd==0)   cout   < <   "Null   pointer   on   second   type-cast "   < <   endl;

    }   catch   (exception&   e)   {cout   < <   "Exception:   "   < <   e.what();}
    return   0;
}

其中:

CBase   *   pba   =   new   CDerived;
CBase   *   pbb   =   new   CBase;

虽然pba   和pbb都指向CBase   *类型.
但pba   实际指向完整的object   of   CDerived.
而pbb指向object   of   CBase,   非完整的object   of   CDerived.

而dynamic_cast会runtime检查 "被转换方的数据完整性 ".

pd   =   dynamic_cast <CDerived*> (pba); <=====   成功!   pba指向完整的object   of   CDerived.

pd   =   dynamic_cast <CDerived*> (pbb); <=====   失败!   pba指向非完整的object   of   CDerived.


总结:dynamic_cast就像它名字一样----要runtime检查 "被转换方的数据完整性 ".

比较static_cast和dynamic_cast
static_cast---靠程序员来检查类型转换的完整性
dynamic_cast---runtime检查类型转换的完整性

有了static_cast和dynamic_cast,就可以在类继承树上随意 "游动 ",获得类型之间的转换.

你可能感兴趣的:(exception,object,null,Class,iostream,fun)