C++中的dynamic_cast

來源:互聯網
上載者:User
dynamic_cast有什麼用?實際上,dynamic_cast是ANSI C++中僅有的兩個與RTTI (Run Time Type Identification) 有關的用法之一。C++的類繼承,使得有時很難弄清楚你正在使用的object屬於哪個class,特別是當繼承樹比較深並且比較複雜的時候,例如,當你在程式中取得一個CWnd*指標,你的意圖是,如果它實際上指向一個dialog對象那麼就調用它的DoModal方法,這個時候,你就需要dynamic_cast: CWnd* pWin = myGetWin();CDialog* pDlg = NULL: if( pDlg = dynamic_cast<CDialog*>(pWin) )    pDlg->DoModal(); 這裡用簡單的強制類型轉換或者static_cast不行嗎?確實是不行的。假如pWin實際指向的是一個View對象,你的程式就會對View對象調用DoModal(),在MFC裡你這樣做或許僅僅會得到一個Assert,有些場合會得到一個segment fault,而按照Effective C++裡面的說法,這樣undefined的用法,也許會導致這個程式向你熱戀中的女友發一封絕交信,呵呵。如果是多線程的程式,這樣的一個問題導致你花上一整天時間瘋狂地打log是很正常的事情。 而使用dynamic_cast,如果實際對象不是CDialog,一個NULL指標會被傳回來。就算你忘記了寫if then,你也可以很快利用調試器定位出錯誤在哪裡。NULL指標的bug大概是所有bug中最幸福的一種。 dynamic_cast做到這一點是利用了編譯器提供的RTTI機制,編譯器會把一個class的類型資訊放在C++ Runtime系統的某處,常常就是在vtbl的末端,這樣從class指標得到vptr,再從vptr得到vtbl,就能夠檢查類型資訊是否匹配。 dynamic_cast的用法之所以少見,是因為它實際上是一種“不好的”用法,某種程度上破壞了O-O的一些基本原則。既然定義了一個基類類型,就是想把衍生類別的差異性隱藏起來,提供一個統一的interface,那麼你又有什麼理由再從外面把這種差異性還原出來呢?不止一本C++經典論述中提到過,在一個設計良好的類繼承體系中,不該為dynamic_cast留下生存空間。 然而,聖經和實際生活總有距離,有時候架構不那麼完美,只是把一堆對象用一個基類指標的數組管理起來,你必須使用某個衍生類別的特定方法,而類庫又沒有為你提供這樣的路徑,你就只好自己動手,把它解構。像上面給出的例子,很難說在實踐中不會遇見這樣的狀況。 也許有人會說,這樣的問題啊,我會自己處理的,用不著什麼RTTI,我會為在基類中添加一個type資料成員,再做一個GetType()方法,每個衍生類別對象在構造的時候賦予不同的值,調用的時候判斷一下,這不就OK了嗎?這樣做當然也可以,但是首先,你的實現效率比編譯器的RTTI實現差遠了,你要為每個object增加一個字的空間開銷,而編譯器則是對一個class增加一點空間,因為編譯器可以利用現有的vptr和vtbl,你卻沒法控制C++ Runtime庫。其次,退一萬步講,為什麼要設計C++呢?完全可以用純正的C程式實作類別封裝、繼承、多態這些機制,無非就是用一堆函數指標嘛!早期的C++程式是怎麼編譯的?是用一個前置處理器先翻譯成C代碼,再用C編譯器去編譯。用了C++,不就是為了少寫一些代碼,程式結構更清楚嘛。因此只要編譯器提供這個功能,就不要再自己去找麻煩。 關於dynamic_cast最有趣的事情在於,主流的C++編譯器為了滿足一些吝嗇的C程式員的要求,一般都提供了把RTTI關掉的編譯選項,這樣確實可以減少一些空間開銷。而如果你使用了這樣的編譯選項,而你的程式中又使用了dynamic_cast,啊哈,美妙的segment fault立即就會向你襲來。 在不少mail-list中都可以看到有人在抱怨dynamic_cast引起的程式崩潰,其中一些使用g++的提問者還明白地知道自己加上了-fno-rtti的選項,回答問題的老大們就往往會用"foolish"來形容這樣的行徑。至於用Visual C++的人就更糟糕了,VC6中的cl編譯器預設設定是關掉RTTI 的,你必須自己在project settings頁面裡把它選上,或者手工添加"/GR"選項。在Windows下面試圖移植OpenH323類庫的同道們,估計肯定有人吃過這個苦頭。 最無辜的程式員是這樣的,他認為使用ANSI C++標準中定義的東西怎麼會有問題呢?但偏偏他遇到了一位熱心的Build Master,為了最佳化效能把RTTI選項給關掉了。我想這個問題,是衡量一個軟體開發隊伍組態管理水平的一個經典題目。  

此日誌的引用 URL 是:http://skywalkerj.spaces.live.com/blog/cns!49c467f1b758d6fc!146.entry?sa=20850098

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.