1. 程式人生 > >C++中的dynamic_cast、static_cast轉換

C++中的dynamic_cast、static_cast轉換

一、static_cast關鍵字(編譯時型別檢查),簡而言之主要用於除基本轉換外的轉換

用法:static_cast < type-id > ( expression ),該運算子把expression轉換為type-id型別,但沒有執行時型別檢查來保證轉換的安全性,它主要有如下幾種用法:

(1)用於基本資料型別之間的轉換,如把int轉換為char,把int轉換成enum,但這種轉換的安全性需要開發者自己保證(這可以理解為保證資料的精度,即程式設計師能不能保證自己想要的程式安全),如在把int轉換為char時,如果char沒有足夠的位元位來存放int的值(int>127或int<-127時),那麼static_cast所做的只是簡單的截斷,及簡單地把int的低8位複製到char的8位中,並直接拋棄高位。

(2)把空指標轉換成目標型別的空指標

(3)把任何型別的表示式型別轉換成void型別

(4)用於類層次結構中父類和子類之間指標和引用的轉換。

對於以上第(4)點,存在兩種形式的轉換,即上行轉換(子類到父類)和下行轉換(父類到子類)。對於static_cast,上行轉換時安全的,而下行轉換時不安全的,為什麼呢?因為static_cast的轉換時粗暴的,它僅根據型別轉換語句中提供的資訊(尖括號中的型別)來進行轉換,這種轉換方式對於上行轉換,由於子類總是包含父類的所有資料成員和函式成員,因此從子類轉換到父類的指標物件可以沒有任何顧慮的訪問其(指父類)的成員。而對於下行轉換為什麼不安全,是因為static_cast只是在編譯時進行型別堅持,沒有執行時的型別檢查,具體原理在dynamic_cast中說明。

二、dynamic_cast關鍵字(執行時型別檢查),簡而言之主要用於上行、下行的指標轉換

用法:同static_cast

dynamic_cast主要用於類層次結構中父類和子類之間指標和引用的轉換,由於具有執行時型別檢查,因此可以保證下行轉換的安全性,何為安全性?即轉換成功就返回轉換後的正確型別指標,如果轉換失敗,則返回NULL,之所以說static_cast在下行轉換時不安全,是因為即使轉換失敗,它也不返回NULL。

對於上行轉換,dynamic_cast和static_cast是一樣的。

對於下行轉換,說到下行轉換,有一點需要了解的是在C++中,一般是可以用父類指標指向一個子類物件,如parent* P1 = new Children(); 但這個指標只能訪問父類定義的資料成員和函式,這是C++中的靜態聯翩,但一般不定義指向父類物件的子類型別指標,如Children* P1 = new parent;這種定義方法不符合生活習慣,在程式設計上也很麻煩。這就解釋了也說明了,在上行轉換中,static_cast和dynamic_cast效果是一樣的,而且都比較安全,因為向上轉換的物件一般是指向子類物件的子類型別指標;而在下行轉換中,由於可以定義就不同了指向子類物件的父類型別指標,同時static_cast只在編譯時進行型別檢查,而dynamic_cast是執行時型別檢查,則需要視情況而定。下面通過程式碼進行說明

class Base {     virtual void fun(){} };

class Derived:public Base { };

由於需要進行向下轉換,因此需要定義一個父類型別的指標Base *P,但是由於子類繼承與父類,父類指標可以指向父類物件,也可以指向子類物件,這就是重點所在。如果 P指向的確實是子類物件,則dynamic_cast和static_cast都可以轉換成功,如下所示:

Base *P = new Derived(); Derived *pd1 = static_cast<Derived *>(P); Derived *pd2 = dynamic_cast<Derived *>(P);

以上轉換都能成功。

但是,如果 P 指向的不是子類物件,而是父類物件,如下所示:

Base *P = new Base; Derived *pd3 = static_cast<Derived *>(P); Derived *pd4 = dynamic_cast<Derived *>(P);

在以上轉換中,static_cast轉換在編譯時不會報錯,也可以返回一個子類物件指標(假想),但是這樣是不安全的,在執行時可能會有問題,因為子類中包含父類中沒有的資料和函式成員,這裡需要理解轉換的字面意思,轉換是什麼?轉換就是把物件從一種型別轉換到另一種型別,如果這時用 pd3 去訪問子類中有但父類中沒有的成員,就會出現訪問越界的錯誤,導致程式崩潰。而dynamic_cast由於具有執行時型別檢查功能,它能檢查P的型別,由於上述轉換是不合理的,所以它返回NULL。

三、總結

C++中層次型別轉換中無非兩種:上行轉換和下行轉換

對於上行轉換,static_cast和dynamic_cast效果一樣,都安全;

對於下行轉換:你必須確定要轉換的資料確實是目標型別的資料,即需要注意要轉換的父類型別指標是否真的指向子類物件,如果是,static_cast和dynamic_cast都能成功;如果不是static_cast能返回,但是不安全,可能會出現訪問越界錯誤,而dynamic_cast在執行時型別檢查過程中,判定該過程不能轉換,返回NULL。