c++的四種強制型別轉換,所以c++不是型別安全的。分別為:static_cast , dynamic_cast , const_cast , reinterpret_cast。
為什麼使用c風格的強制轉換可以把想要的任何東西轉換成合乎心意的型別。那為什麼還需要乙個新的c++型別的強制轉換呢?新型別的強制轉換可以提供更好的控制強制轉換過程,允許控制各種不同種類的強制轉換。
c++中風格是static_cast(content)。c++風格的強制轉換其他的好處是,它們能更清晰的表明它們要幹什麼。程式設計師只要掃一眼這樣的**,就能立即知道乙個強制轉換的目的。
1、隱式型別轉換
何時發生隱式型別轉換?在下面這些情況下,編譯器會自動地轉換運算物件的型別:
- 在大多數表示式中,比int型別小的整型值首先提公升為較大的整數型別;
- 在條件中,非布林值轉換為布林型別;
- 初始化過程中,初始值轉換成變數的型別;在賦值語句中,右側運算物件轉換成左側運算物件的型別;
- 如果算術運算或關係運算的運算物件有多種型別,需要轉換成同一種型別;
- 函式呼叫時也會發生型別轉換。
除了算術轉換之外還有幾種隱式轉換,包括如下幾種:
1、陣列轉換成指標: 在大多數用到陣列的表示式中,陣列自動轉換成指向陣列首元素的指標:
int ia[10]; //含有10個整數的陣列
int *ip=ia; //ia轉換成指向陣列首元素的指標
當陣列被用作decltype關鍵字的引數,或者作為取位址符(&)、sizeof及typeid等運算子的運算物件時,上述轉換不會發生。同樣的,如果用乙個引用來初始化陣列,上述轉換也不會發生。
2、指標的轉換:
c++還規定了幾種其他轉換方式,包括常量整數值0或字面值nullptr能轉換成任意指標型別;指向任意非常量的指標能轉換成void*;指向任意物件的指標能轉換成const void*。
3、轉換成布林型別:
存在一種從算術型別或指標型別向布林型別自動轉換的機制。如果指標或算術型別的值為0,轉換結果為false;否則轉換結果是true;
4、轉換成常量:
允許將指向非常量型別的指標轉換成指向相應的常量型別的指標,對於引用也是這樣。也就是說,如果t是一種型別,我們就能將指向t的指標或引用分別轉換成指向const t的指標或引用。相反的轉換不存在,因為它試圖刪除掉底層const。
5、類型別定義的轉換:
類型別能定義由編譯器自動執行的轉換,不過編譯器每次只能執行一種類型別的轉換。
2、顯式型別轉換
關於強制型別轉換的問題,很多書都討論過,寫的最詳細的是c++ 之父的《c++ 的設計和演化》。最好的解決方法就是不要使用c風格的強制型別轉換,而是使用標準c++的型別轉換符:static_cast, dynamic_cast。標準c++中有四個型別轉換符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。下面對它們一一進行介紹。
1、static_cast
用法:static_cast < type-id > ( expression )
說明:該運算子把expression轉換為type-id型別,但沒有執行時型別檢查來保證轉換的安全性。
情況1:void指標->其他型別指標
情況2:改變通常的標準轉換
情況3:避免出現可能多種轉換的歧義
int c=static_cast
(7.987);//如果涉及到類的話,static_cast只能在有相互聯絡的型別中進行相互轉換,不一定包含虛函式。
class a{};
class b:public a{};
class c{};
int main()
2、dynamic_cast
用法:dynamic_cast < type-id > ( expression )
說明:該運算子把expression轉換成type-id型別的物件。type-id必須是類的指標、類的引用或者void *;如果type-id是類指標型別,那麼expression也必須是乙個指標,如果type-id是乙個引用,那麼expression也必須是乙個引用。
簡單的說,當無法使用virtual函式的時候。
【note】:
(1)其他三種都是編譯時完成的,dynamic_cast是執行時處理的,執行時要進行型別檢查。
(2)不能用於內建的基本資料型別的強制轉換。
(3)dynamic_cast轉換如果成功的話返回的是指向類的指標或引用,轉換失敗的話則會返回null。
(4)使用dynamic_cast進行轉換的,基類中一定要有虛函式,否則編譯不通過。需要檢測有虛函式的原因:類中存在虛函式,就說明它有想要讓基類指標或引用指向派生類物件的情況,此時轉換才有意義。 這是由於執行時型別檢查需要執行時型別資訊,而這個資訊儲存在類的虛函式表, 只有定義了虛函式的類才有虛函式表。
(5)在類的轉換時,在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的。在進行下行轉換時,dynamic_cast具有型別檢查的功能,比 static_cast更安全。
void dosomething(flyable *obj)
if(typeid(*obj) == typeid(plane))
obj->land();
}
3、reinpreter_cast
用法:reinpreter_cast (expression)
說明:type-id必須是乙個指標、引用、算術型別、函式指標或者成員指標。它可以把乙個指標轉換成乙個整數,也可以把乙個整數轉換成乙個指標(先把乙個指標轉換成乙個整數,在把該整數轉換成原型別的指標,還可以得到原先的指標值)。它可以轉化任何內建的資料型別為其他任何的資料型別,也可以轉化任何指標型別為其他的型別。它甚至可以轉化內建的資料型別為指標,無須考慮型別安全或者常量的情形。不到萬不得已絕對不用。
4、const_cast
用法:const_cast (expression)
說明:該運算子用來修改型別的const或volatile屬性。除了const 或volatile修飾之外, type_id和expression的型別是一樣的。它可以使乙個本來不是const型別的資料轉換成const型別的,或者把const屬性去掉。
常量指標被轉化成非常量指標,並且仍然指向原來的物件;常量引用被轉換成非常量引用,並且仍然指向原來的物件;常量物件被轉換成非常量物件。
class b
void foo()
上面的**編譯時會報錯,因為b1是乙個常量物件,不能對它進行改變;使用const_cast把它轉換成乙個常量物件,就可以對它的資料成員任意改變。注意:b1和b2是兩個不同的物件。 c 四種強制轉換
c 同時提供了四種新的強制轉型形式 通常稱為新風格的或 c 風格的強制轉型 const cast expression dynamic cast expression reinterpret cast expression static cast expression 每一種適用於特定的目的 con...
C 四種強制轉換
c 的四種強制型別轉換,所以c 不是型別安全的。分別為 static cast dynamic cast const cast reinterpret cast 為什麼使用c風格的強制轉換可以把想要的任何東西轉換成合乎心意的型別。那為什麼還需要乙個新的c 型別的強制轉換呢?新型別的強制轉換可以提供更...
C 四種強制轉換
c 的四種強制型別轉換,所以c 不是型別安全的。分別為 static cast dynamic cast const cast reinterpret cast 為什麼使用c風格的強制轉換可以把想要的任何東西轉換成合乎心意的型別。那為什麼還需要乙個新的c 型別的強制轉換呢?新型別的強制轉換可以提供更...