C中的類型轉換:
事情要從頭說起,這個頭就是C語言.我們已經習慣了使用C-like類型轉換,因為它強大而且簡單.
主要有一下兩種形式:
(new-type) expression
new-type (expression)
C風格的轉換格式很簡單,但是有不少缺點:
1.轉換太過隨意,可以在任意類型之間轉換。你可以把一個指向const對象的指標轉換成指向非const對象的指標,把一個指向基類對象的指標轉換成一個衍生類別對象的指標,這些轉換之間的差距是非常巨大的,但是傳統的C語言風格的類型轉換沒有區分這些。
2.C風格的轉換沒有統一的關鍵字和標示符。對於大型系統,做代碼排查時容易遺漏和忽略。
C++中的類型轉換:
C++風格完美的解決了上面兩個問題。1.對類型轉換做了細分,提供了四種不同類型轉換,以支援不同需求的轉換;2.類型轉換有了統一的標示符,利於代碼排查和檢視。下面分別來介紹這四種轉換:static_cast、dynamic_cast、const_cast和reinterpreter_cast.
static_cast,命名上理解是靜態類型轉換。如int轉換成char。
dynamic_cast,命名上理解是動態類型轉換。如子類和父類之間的多態類型轉換。
const_cast,字面上理解就是去const屬性。
reinterpreter_cast,僅僅重新解釋類型,但沒有進行二進位的轉換。
一、static_cast轉換
1.基本用法:static_cast expression
2.使用情境:
a、用於類階層中基類和衍生類別之間指標或引用的轉換
上行轉換(衍生類別—->基類)是安全的;
下行轉換(基類—->衍生類別)由於沒有動態類型檢查,所以是不安全的。
b、用於基礎資料型別 (Elementary Data Type)之間的轉換,如把int轉換為char,這種帶來安全性問題由程式員來保證
c、把null 指標轉換成目標類型的null 指標
d、把任何類型的運算式轉為void類型
3.使用特點
a、主要執行非多態的轉換操作,用於代替C中通常的轉換操作
b、隱式轉換都建議使用static_cast進行標明和替換
int n = 6;double d = static_cast<double>(n); // 基本類型轉換int *pn = &n;double *d = static_cast<double *>(&n) //無關類型指標轉換,編譯錯誤void *p = static_cast<void *>(pn); //任意類型轉換成void類型
二、dynamic_cast轉換
1.基本用法:dynamic_cast expression
2.使用情境:只有在衍生類別之間轉換時才使用dynamic_cast,type-id必須是類指標,類引用或者void*。
3.使用特點:
a、基類必須要有虛函數,因為dynamic_cast是運行時類型檢查,需要運行時類型資訊,而這個資訊是儲存在類的虛函數表中,只有一個類定義了虛函數,才會有虛函數表(如果一個類沒有虛函數,那麼一般意義上,這個類的設計者也不想它成為一個基類)。
b、對於下行轉換,dynamic_cast是安全的(當類型不一致時,轉換過來的是null 指標),而static_cast是不安全的(當類型不一致時,轉換過來的是錯誤意義的指標,可能造成踩記憶體,非法訪問等各種問題)
c、dynamic_cast還可以進行交叉轉換
class BaseClass {public: int m_iNum; virtual void foo(){};//基類必須有虛函數。保持多台特性才能使用dynamic_cast};class DerivedClass: public BaseClass {public: char *m_szName[100]; void bar(){};}; BaseClass* pb = new DerivedClass();DerivedClass *pd1 = static_cast<DerivedClass *>(pb);//子類->父類,靜態類型轉換,正確但不推薦DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb);//子類->父類,動態類型轉換,正確BaseClass* pb2 = new BaseClass();//父類->子類,靜態類型轉換,危險!訪問子類m_szName成員越界DerivedClass *pd21 = static_cast<DerivedClass *>(pb2);//父類->子類,動態類型轉換,安全的。結果是NULLDerivedClass *pd22 = dynamic_cast<DerivedClass *>(pb2);
三、const_cast轉換
1.基本用法:const_castexpression
2.使用情境:
a、常量指標轉換為非常量指標,並且仍然指向原來的對象
b、常量引用被轉換為非常量引用,並且仍然指向原來的對象
3.使用特點:
a、cosnt_cast是四種類型轉換符中唯一可以對常量進行操作的轉換符
b、去除常量性是一個危險的動作,盡量避免使用。一個特定的情境是:類通過const提供重載時,一般都是非常量函數調用const_cast將參數轉換為常量,然後調用常量函數,然後得到結果再調用const_cast 去除常量性。
struct SA { int i;};const SA ra;//ra.i = 10; //直接修改const類型,編譯錯誤SA &rb = const_cast<SA&>(ra);rb.i = 10;
四、reinterpret_cast轉換
1.基本用法:reinterpret_castexpression
2.使用情境:不到萬不得已,不用使用這個轉換符,高危操作
3.使用特點:
a、reinterpret_cast是從底層對資料進行重新解釋,依賴具體的平台,可移植性差
b、reinterpret_cast可以將整型轉換為指標,也可以把指標轉換為數組
c、reinterpret_cast可以在指標和引用裡進行肆無忌憚的轉換
int doSomething(){return 0;};//FuncPtr is 一個指向函數的指標,該函數沒有參數,傳回值類型為 voidtypedef void(*FuncPtr)();//10個FuncPtrs指標的數組 讓我們假設你希望(因為某些莫名其妙的原因)把一個指向下面函數的指標存//入funcPtrArray數組:FuncPtr funcPtrArray[10];funcPtrArray[0] = &doSomething;// 編譯錯誤!類型不符,reinterpret_cast可以讓編譯器以你的方法去看待它們:funcPtrArrayfuncPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);//不同函數指標類型之間進行轉換
總結:
去const屬性用const_cast。
基本類型轉換用static_cast。
多態類之間的類型轉換用daynamic_cast。
不同類型的指標類型轉換用reinterpreter_cast。
相關文章:
C++ 的強制類型轉換
【c#教程】C# 類型轉換
相關視頻:
PHP資料類型轉換之自動類型轉換