關於dynamic_cast
有時候,專案需求緊,時間少,寫程式碼往往就抓起什麼用什麼,比較少考慮設計的合理性。dynamic_cast就是一例。
dynamic_cast一般用於down cast,即將父類的指標(或引用)轉換成子類的指標(或引用),並提供了執行時的型別檢查(RTTI功能),轉換失敗時,會返回一個nullptr(引用則丟擲bad cast異常)。
在菱形繼承關係中,還可以完成到兄弟型別的轉化,不過如果涉及到菱形繼承,我覺得還是應該立馬審視下當前的型別設計結構,太複雜了,《深入理解C++物件模型》沒讀過10遍以上,很容易出問題=-=
我遇到的問題比較簡單,幾個protobuf的訊息物件,可以通過一個列舉型別的變數區分。在處理邏輯中需要對它們分別進行處理,但是處理邏輯中,有一大塊的邏輯是通用的。
考慮到protobuf的訊息型別全部繼承自protobuf::Message,於是我將這一塊通用邏輯,抽象成了一個共用函式,以protobuf::Message的指標為引數。
在這個共用函式中,又有部分邏輯是針對各個特定的訊息MessageA,MessageB……的,於是在這裡,我根據上面說到的可以用於區分型別的列舉物件,將Message*指標分別dynamic_cast到MessageA*,MessageB*等,然後進行特殊的邏輯。
但是,dynamic_cast是有效能損失的,畢竟要動態檢查型別。有人測算過,dynamic_cast對比static_cast,時延要多4倍。而在我的程式裡,消除掉dynamic_cast之後,時延可以縮短40%左右。
其實,大部分的down cast,都可以通過繼承、過載來實現。這樣就把需要線上做的動態型別判斷,放到編譯期完成了。
針對我這裡的需求,其實完全可以把通用的邏輯,用模板的方式實現,再配合同名不同參函式的過載,分別實現針對子型別特有的邏輯。這樣,在編譯期,就為每一種型別生成了自己獨立的邏輯通路,執行時就可以完全規避掉動態型別轉換,從而提高效能。
畢竟,程式碼裡各處xxx_cast<>,看起來還是非常不舒服的,是吧?
據說,C++在設計之初,型別轉換中引入static_cast,dynamic_cast,reinterpret_cast這麼多難以拼寫的cast,就是為了讓大家儘量少用……
轉載請註明出處: http://blog.guoyb.com/2018/11/03/dynamic_cast/
歡迎使用微信掃描下方二維碼,關注我的微信公眾號TechTalking,技術·生活·思考:
