C++四種類型轉換

C++提供了四種新式類型轉換(常常被稱爲new-style或C++-style casts):

const_cast<T>(exception)

static_cast<T>(exception)

dynamic_cast<T>(exception)

reinterpret_cast<T>(exception)

注意:強制類型轉換干擾了正常的類型檢查,因此,我們強烈建議程序猿避免使用強制類型轉換。這個建議對於reinterpret_cast尤其試用,因爲此類型轉換總是充滿了危險。

const_cast

通常被用來將對象的常量性移除(cast away the constness)。它也是唯一有此能力的C++style轉型操作符。
const char* pc;
char *p=const_cast<char*>(pc);
const_cast常常用於有函數重載的上下文中。
class TextBlock{  
public:  
……  
const char& operator[](size_t position) const{  
……  
……  
return text[position];  
}  
char& operator[](size_t position){  
return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);//先添加const屬性,再移除。  
}  
……  
};


dynamic_cast

主要用來執行安全向下轉型(safe downcasting),也就是用來決定某對象是否歸屬繼承體系中的某個類型。它是唯一無法由舊式語法執行的動作,也是唯一可能耗費重大運行成本的轉型動作。
運行時類型識別(run-time type identification,RTTI)的功能由兩個運算符實現:
  • typeid運算符,用於返回表達式的類型。
  • dynamic_cast運算符,用於將基類的指針或引用安全的轉換成派生類的指針或引用。
當我們將這兩個運算符用於某種類型的指針或引用,並且該類型含有虛函數時,運算符將使用指針或引用所綁定對象的動態類型。
這兩個運算符特別適用於以下情況:我們想使用基類對象的指針或引用執行某個派生類操作並且該操作不是虛函數。一般來說,只要有可能我們應該儘量使用虛函數。當操作被定義成虛函數時,編譯器將根據對象的動態類型自動的選擇正確的函數版本。
然而並非任何時候都能定義一個虛函數。假設我們無法使用虛函數,則可以使用一個RTTI運算符。另一方面,與虛成員函數相比,使用RTTI運算符蘊含着更多潛在風險:程序猿必須清楚的知道轉型的目標類型並且必須檢查類型轉換是否被成功執行。
dynamic_cast運算符使用形式如下所示(type必須爲一個類型,且通常情況下該類型應該含有虛函數):
dynamic_cast<type*>(e)          //e必須是一個有效指針
dynamic_cast<type&>(e)         //e必須是一個左值
dynamic_cast<type&&>(e)         //e不能是左值
在上面的形式中e的類型必須符合以下三個條件中的任意一個:e的類型是目標type的公有派生類、e的類型是目標type的公有積基類或者e的類型就是目標type的類型。如果符合則轉型成功,否則轉型失敗。如果一條dynamic_cast語句的轉換目標是指類型並且失敗了,則記過爲0.如果轉換目標是引用類型並且失敗了,則dynamic_cast運算符將拋出一個bad_cast異常。



reinterpret_cast

意圖執行低級轉型,實際動作及結果可能取決於編譯器,這也表示它不可移植。例如講一個pointer to int轉型爲一個int。這一類轉型在低級代碼以外很少見。
int *ip;
char *pc=reinterpret_cast<char*>(ip);
我們必須牢記pc所指的真實對象時一個int而非字符,如果把PC當成普通的字符指針使用就可能在運行時發生錯誤。
string str(pc);//可能導致異常的運行時行爲。
使用reinterpret_cast是非常危險的,用pc初始化str的例子很好地證明了這一點。其中的關鍵問題是類型改變了,但編譯器沒給出任何警告或者錯誤的提示信息。當我們使用一個int地址初始化pc時,由於現實的聲稱這種轉換合法,所以編譯器不會發出任何警告或錯誤信息。接下來再使用pc時就會認定它的值是char*類型,編譯器沒法知道它實際存放的是指向int的指針。最終結果就是,在上面的例子中雖然用pc初始化str沒什麼實際意義,甚至還可能引發更糟糕的後果,但僅從語法上而言這種操作無可指摘。查找這類問題的原因非常困難,如果將ip強制轉換成pc的語句和用pc初始化爲string對象的語句分數不同文件就更是如此。


static_cast

用來強迫隱式轉型(implicit conversions),例如將non-const對象轉爲const對象,獲獎int轉爲double等等。它也可以用來執行上述多種轉換的反向轉換,例如將void*指針轉換爲typed指針,將pointer-to-base轉爲pointer-to-derived。但是它無法將const轉爲non-const——這個只有const_cast才辦得到。
也就是說,任何具有明確定義的類型轉換,只要不包含底層const,都可以使用static_cast。
//進行強制類型轉換以便執行浮點數除法。
double slope=static_cast<double>(j)/i;



以上內容整理自《C++primer》《Effective C++》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章