static_cast和dynamic_cast的區別,看完這篇你就懂了!

_hello_cc發表於2020-12-26

看了很久了這兩個到底是怎麼回事,終於今天幡然悔悟。還是要多讀書呀。

在C++ primer plus的15章第5節裡有介紹:

1  dynamic_cast :

    dynamic_cast的語法:

           dynamic_cast <type_name> (expression)

    書上有兩個地方說了dynamic_cast的用途:

dynamic_cast運算子的用途是,使得能夠在類層次中進行向上轉換

 

僅當Low是High的可訪問基類時,下面的語句才會將一個Low*指標賦給pl:
pl = dynamic_cast<Low*>ph ; //說明下其中ph是派生類指標,pl是基類指標
否則,該語句將空指標賦值給pl

 

由此可見:使用dynamic_cast的用途是:實現安全的向上轉換,如果轉換不成功,那麼就會把被賦值的指標賦值為nullptr .

 

2  static_cast :

    static_cast的語法:

               static_cast <type_name> (expression)    

     主要用於將expression型別強制轉換為type_name誒型. 那麼我們需要知道如何判定轉換是否合法?

     書上的轉換是否合法是這麼判定的,姑且稱為轉換合法原則:

當type_name可被隱式轉換為expression所屬的型別或者expression可被隱式轉換為type_name所屬的型別時,轉換是合法的,否則將出錯

   摘錄出來就是:

    以下條件主要滿足任一條,轉換合法:

           1 ) type_name可被隱式轉換為expression所屬的型別 ;

           2)  expression可被隱式轉換為type_name所屬的型別. 

    我們結合書上給出的例子來看一下: 

     High 是一個基類  ,Low是 High類的一個派生類,有如下程式碼:

High bar;    //基類
Low  blow;   //派生類

...

High *pb = static_cast<High *>(&blow);   //blow是派生類,pb是基類的指標,因此這裡是向上轉換,合法
Low *pl  = static_cast<Low *>(&bar);     //bar是基類,pl是派生類指標,因此是向下轉換,合法

     為什麼上述兩個轉換都是合法的呢?

        其實原因就一條,我們都知道,在派生關係中, 基類的指標可以直接指向一個派生類的物件,這個過程不需要顯式轉換 ,因此結合上述的轉換合法原則,我們來分析一下上述兩句轉換的合法性:

         1) High *pb = static_cast<High *>(&blow);   // High *是 type_name ,&blow所屬的型別是Low * ,  因為 High* 可以被隱式的轉換為Low* ,這符合轉換合法原則的前種情況 " type_name可被隱式轉換為expression所屬的型別" ,因此轉換合法;   

         2) Low *pl  = static_cast<Low *>(&bar);       // Low *是 type_name ,&bar所屬的型別是High *   ,還是因為 High* 可以被隱式的轉換為Low* ,這符合轉換合法原則的後種情況  "expression可被隱式轉換為type_name所屬的型別",因此轉換合法.

 

       因此,我們可以看到static_cast可以把原來只允許單向轉換的場景變成允許雙向轉換,類似的情況有:

       1 一般來說,可以把任意的資料型別指標賦值給void *指標  ,但是不能把 void *指標賦值給任意資料型別的指標, 如果使用了static_cast ,那麼就可以實現把void * 賦值給 任意資料型別;

       2 一般來說, 我們可以把int型別賦值給double型別,但是不能把 double型別的賦值給int型別 ,但如果使用了static_cast ,那麼就可以把double型別賦值給int型別

       3 一般來說,我們可以把一個列舉型別enum直接賦值給int ,但是不能把int直接轉換為enum,但如果使用了static_cast ,那麼就可以實現這種轉換

        ....

        類似的情況,大家可以繼續發散..總之 ,原則就一條 : 能不能合法轉換,主要取決於type_name和expression之間要存在任一方向的隱式轉換關係.

        但是至於轉換後的內容是否安全,這是開發需要自行保證的,編譯器無法保證.

       

       

 

        

 

   

 

 

相關文章