C++標準類型轉換

來源:互聯網
上載者:User
0 -- C++ Primer的強烈建議

強制類型轉換關閉或掛起了正常的類型檢查。強烈建議避免使用強制類型轉換,不依賴類型轉換也能寫出很好的C++程式。

這個建議在如何看待 reinterpret_cast 的使用時非常重要。此類強制轉換總是非常危險的。相似地,使用價格const_cast也總是預示著設計許可權。設計合理的系統應不需要使用強制轉換拋棄const特性。其他的強制轉換,如static_cast和dynamic_cast,各有各的用途,但都不應頻繁使用。每次使用強制轉換前,程式員應該仔細考慮是否還有其他不同的方法可以達到同一目的。如果非強制轉換不可,則應限制強制轉換值的範圍,並且記錄所有假定涉及的類型,這樣能減少錯誤發生的機會。1 -- const_cast<type>(expression)

該運算子將轉換掉expression的const性質。

通過下面的程式碼片段展示const_cast的使用情境:

void print(char * s){printf("%s\n", s);}std::string s = "motadou.cnblogs.com";print(s.c_str()); //編譯失敗,因為s.c_str()結果為const *,與print函數的類型不符。print(const_cast<char *>(s.c_str()); //成功

使用const_cast需要注意的問題:

該類型轉換符除了添加或刪除const屬性外,執行其他任何類型轉換,都會引起編譯錯誤。

2 -- static_cast<type-id>(expression)

該運算子把expression轉換為type-id類型,但沒有運行時類型檢查來保證轉換的安全性。它主要有如下幾種用法:

(1)基類和子類之間指標或引用的轉換

上行轉換(子類指標或引用-->基類指標或引用)是安全的,類型不符時編譯報錯;

下行轉換(基類指標或引用-->子類指標或引用)時,由於沒有動態類型檢查,所以是不安全的。建議使用dynamic_cast。

(2)基礎資料型別 (Elementary Data Type)之間的轉換

如把int轉換成char,把int轉換成enum。這種轉換的安全性也要開發人員來保證。

(3)把void *指標轉換成目標類型的指標

(4)把任何類型的指標轉換成void *類型。

使用static_cast需要注意如下幾個問題:

(1)所謂下行轉換的不安全性,指的是如果類CA、CB均繼承自CBase,用個基類指標表示CA*指標,然後使用static_cast將該基類指標轉換為CB*指標,直接使用這個CB*指標訪問類CB內的資料成員將存在風險。比如:

#include <iostream>class CBase{};class CA : public CBase{public:void print(){ std::cout << "==CA::print==" << std::endl; }};class CB : public CBase{public:void print(){ std::cout << "==CB::print==" << psz_name << std::endl; }char * psz_name;};int main(){CBase * pa = new CA();CB * pb = static_cast(pa);pb->print();return 0;}

上述代碼能夠順利的通過編譯,真正執行程式時會發生什嗎?使用指標pb調用CB::print,由於CB的psz_name並沒有分配空間,事實上是個野指標,非法訪問野指標肯定導致程式coredump。

(2)static_cast不能轉換無關類型(非基類和子類)的指標。比如:

char c_menu = 'c';//下面的類型轉換錯誤,編譯提示:invalid static_cast from type `char*' to type `signed char*signed char * psc_menu = static_cast<signed char *>(&c_menu);

char *和signed char *不是同一類型的指標,static_cast無法轉換故編譯報錯。

(3)static_cast不能轉換掉expression的const、volatile、__unaligned屬性。

3 -- dynamic_cast<type-id>(expression)

該運算子把expression轉換為type-id類型,轉換時進行類型檢查來保證轉換的安全性。它主要有如下幾種用法:

(1)將基類類型對象的引用或指標安全地轉換為同一繼承層次中其他類型的引用或指標。轉換時進行類型檢查,如果發現綁定到引用或者指標的對象不是目標類型的對象,則轉換失敗。

使用dynamic_cast需要注意如下幾個問題:

(1)類必須有虛函數,否則編譯報錯(編譯器將提示不含有虛函數)。原因是轉換過程中需要運行時類型資訊,該資訊儲存在類的虛函數表中,只有定義虛函數,類才有虛函數表。

(2)與dynamic_cast一起使用的指標必須是有效--它必須為0或者指向一個對象。

(3)type-id和expression要麼同是引用,要麼同是指標。

(4)上行轉換,dynamic_cast與static_cast的效果相同。

(5)下行轉換,dynamic_cast進行運行時類型檢查,類型符合則成功轉換,否則轉換失敗。失敗表現為:轉換指標類型時,dynamic_cast返回結果NULL;轉換參考型別時,拋出std::bad_cast異常。

(6)相同基類不同子類之間的交叉轉換均為失敗,表現與上述相同。

5 -- reinterpret_cast<type>(expression)

該操作符只進行簡單的位元位拷貝,將expression的所有位元位拷貝給type-id一份。可以說僅僅是重新解釋了給出的對象的位元模型。該操作符和C語言的強制轉換,最為類似。

所謂重新解釋位元模型,我們可以這麼理解:假設有個指向int類型的指標pint,使用double * pdouble = reinterpret_cast<double *>(pint)進行轉換。實際只是將pint的4個位元組拷貝給pdouble。我們知道pint指向的空間是4個位元組,而理論上pdouble應該指向8個位元組,但此時pdouble指向的其他4個位元組將是非法資料。重新解釋位元模型,就是把int值的空間,當做double類型來使用。該操作符相當危險,因此必須謹慎使用。

使用reinterpret_cast需要注意如下幾個問題: (1)上面提到static_cast不能進行無關類型的轉換,reinterpret_cast可以做到,但需注意轉換的安全性。 (2)reinterpret_cast本質上依賴於機器。為了安全地使用reinterpret_cast,要求程式員完全理解所涉及的資料類型,以及編譯器實現強制類型轉換的細節。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.