我據說static_cast
函數應該比C樣式或簡單的函數樣式轉換更可取。 這是真的? 爲何? 前端
除處理指向類的指針外,static_cast還能夠用於執行在類中顯式定義的轉換,以及在基本類型之間執行標準轉換: 安全
double d = 3.14159265; int i = static_cast<int>(d);
static_cast
意味着您不能偶然const_cast
或reinterpret_cast
,這是一件好事。 函數
這是關於您要強加多少類型安全性。 工具
當您編寫(bar) foo
(若是您未提供類型轉換運算符,則至關於reinterpret_cast<bar> foo
),您是在告訴編譯器忽略類型安全性,並按照提示執行操做。 spa
在編寫static_cast<bar> foo
您要求編譯器至少檢查類型轉換是否有意義,對於整數類型,請插入一些轉換代碼。 指針
編輯2014-02-26 code
我在5年前就寫了這個答案,但我弄錯了。 (請參閱評論。)可是它仍然會被投票! 對象
一個實用的技巧:若是您打算整理項目,則能夠在源代碼中輕鬆搜索static_cast關鍵字。 繼承
主要緣由是經典C強制轉換在咱們稱爲static_cast<>()
, reinterpret_cast<>()
, const_cast<>()
和dynamic_cast<>()
之間沒有區別。 這四件事徹底不一樣。 編譯器
static_cast<>()
一般是安全的。 語言存在有效的轉換,或者使之成爲可能的適當的構造函數。 惟一有風險的是當您降級爲繼承的類時。 您必須經過語言外部的方式(例如對象中的標記)確保該對象其實是您聲稱的對象的後代。 只要檢查結果(指針)或考慮到可能的異常(引用), dynamic_cast<>()
都是安全的。
另外一方面, reinterpret_cast<>()
(或const_cast<>()
)始終很危險。 您告訴編譯器:「相信我:我知道這看起來不像foo
(看起來好像是不可變的),可是確實如此。」
第一個問題是,在不查看大量分散代碼並知道全部規則的狀況下,幾乎不可能分辨出將在C樣式轉換中發生哪個。
讓咱們假設這些:
class CDerivedClass : public CMyBase {...}; class CMyOtherStuff {...} ; CMyBase *pSomething; // filled somewhere
如今,這兩種編譯方式相同:
CDerivedClass *pMyObject; pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<> // Safe; as long as we checked // but harder to read
可是,讓咱們看一下幾乎相同的代碼:
CMyOtherStuff *pOther; pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert pOther = (CMyOtherStuff*)(pSomething); // No compiler error. // Same as reinterpret_cast<> // and it's wrong!!!
如您所見,在不瞭解全部涉及的全部類的狀況下,沒有簡單的方法來區分這兩種狀況。
第二個問題是C樣式轉換很難定位。 在複雜的表達式中,很難看到C樣式的強制轉換。 在沒有完整的C ++編譯器前端的狀況下,幾乎不可能編寫須要定位C樣式轉換的自動化工具(例如搜索工具)。 另外一方面,很容易搜索「 static_cast <」或「 reinterpret_cast <」。
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething); // No compiler error. // but the presence of a reinterpret_cast<> is // like a Siren with Red Flashing Lights in your code. // The mere typing of it should cause you to feel VERY uncomfortable.
這意味着,不只C風格的強制轉換更加危險,並且要確保它們正確無誤地查找它們要困可貴多。