C++型別轉換
C++有可以使用static_cast、dynamic_cast、const_cast、reinterpret_cast來進行型別的轉換。現在將每一個的使用方法進行一下總結。
1.static_cast
這個運算子的功能是把一個表示式轉換為某種型別,但是沒有執行時型別檢查來保證轉換的安全性。可以用來轉換的型別主要如下:
- 類中基類和派生類之間的指標或者引用的轉換:向上轉換是安全的(派生類的指標轉換為基類),但是向下轉換的時候由於沒有型別檢查,所有是不安全的。
- 基本資料型別之間的轉換。
- 空指標轉換為目標型別的空指標。
- 任何型別的表示式轉換為void型別。
static_cast不能把原來表示式中的const、volatile、_unaligned屬性轉換成沒有。請看下面例子
1 char firstChar = 'A'; 2 int firstInt = static_cast<int>(firstChar); 3 const char* constStr = "this is a test string"; 4 char* str = static_cast<char*>(constStr);
上面的第4行程式碼是不能編譯通過的。
2.dynamic_cast
dynamic_cast的轉換需要目標型別和源物件有一定的關係:繼承關係。換句話說就是dynamic_cast就是用來檢查兩者是否有繼承關係,所有dynamic_cast只能接受類物件的指標或者是引用的類轉換。用法表示式如下:
dynamic_cast<type_id>(expession)。type_id只能是類的指標、引用或者是void*。如果type_id是一個指標或者引用,那麼expression也必須是指標或者引用,type_id和expression必須對應起來。
dynamic_cast在執行的時候決定真正的型別,如果轉換是安全的,dynamic_cast就會傳回適當的轉換過的指標,如果轉換是不安全的,就會返回空指標。
在類層次向上轉換的時候,dynamic_cast和static_cast的效果是一樣的。
在類層次向下轉換的時候,由於dynamic_cast會做型別檢查,所有比static_cast更加的安全。如下的例子:
class person { public: int n_num; virtual void doSomething() { cout << "i am a person" << endl; } }; class colorPerson :public person { public: char* mName; }; void change(person *person) { colorPerson * cp1 = static_cast<colorPerson*>(person); cout << "start to call cp1" << endl; if (cp1 != NULL) { cp1->doSomething(); } else { cout << "cp1 is null" << endl; } colorPerson *cp2 = dynamic_cast<colorPerson*>(person); cout << "start to call cp2" << endl; if (cp2!= NULL) { cp2->doSomething(); } else { cout << "cp2 is null" << endl; } } int main() { person *p1=new person(); change(p1); colorPerson *cp1 = new colorPerson(); change(cp1); return 0; }View Code
輸出結果是這樣的:
在定義person類的時候,我們是定義了一個virtual的dosomething(),這個virtual對應dynamic_cat是必須的,如果沒有virtual,就會報編譯錯誤。因為dynamic_cast轉換是在執行時進行轉換,執行時轉換就需要知道類物件的資訊(繼承關係等)。如何在執行時獲取到這個資訊——虛擬函式表。