在面向對象程序設計中,有時咱們須要在運行時查詢一個對象是否能做爲某種多態類型使用。與Java的instanceof,以及C#的as、is運算符相似,C++提供了dynamic_cast
函數用於動態轉型。相比C風格的強制類型轉換和C++ reinterpret_cast
,dynamic_cast
提供了類型安全檢查,是一種基於能力查詢(Capability Query)的轉換,因此在多態類型間進行轉換更提倡採用dynamic_cast
。本文主要介紹dynamic_cast
的意義,用法和注意事項。安全
基本用法函數
dynamic_cast
能夠獲取目標對象的引用或指針:設計
T1 obj; T2* pObj = dynamic_cast<T2*>(&obj); //轉換爲T2指針,失敗返回NULL T2& refObj = dynamic_cast<T2&>(obj); //轉換爲T2引用,失敗拋出bad_cast異常
多態類型指針
在使用時須要注意:被轉換對象obj的類型T1
必須是多態類型,即T1
必須公有繼承自其它類,或者T1
擁有虛函數(繼承或自定義)。若T1
爲非多態類型,使用dynamic_cast
會報編譯錯誤。下面的例子說明了哪些類屬於多態類型,哪些類不是:code
//A爲非多態類型 class A{ }; //B爲多態類型 class B{ public: virtual ~B(){} }; //D爲多態類型 class D: public A{ }; //E爲非多態類型 class E : private A{ }; //F爲多態類型 class F : private B{ };
橫向轉型對象
在多態類型間轉換,分爲3種類型:
1.子類向基類的向上轉型(Up Cast)
2.基類向子類的向下轉型(Down Cast)
3.橫向轉型(Cross Cast)繼承
向上轉型是多態的基礎,需不要藉助任何特殊的方法,只需用將子類的指針或引用賦給基類的指針或引用便可,固然dynamic_cast
也支持向上轉型,而其老是確定成功的。而對於向下轉型和橫向轉型來說,其實對於dynamic_cast
並無任何區別,它們都屬於能力查詢。爲了理解方便,咱們不妨把dynamic_cast
視爲cross cast:it
class Shape { public: virtual ~Shape(); virtual void draw() const = 0; }; class Rollable { public: virtual ~Rollable(); virtual void roll() = 0; }; class Circle : public Shape, public Rollable { void draw() const; void roll(); }; class Square : public Shape { void draw() const; }; //橫向轉型失敗 Shape *pShape1 = new Square(); Rollable *pRollable1 = dynamic_cast<Rollable*>(pShape2);//pRollable爲NULL //橫向轉型成功 Shape *pShape2 = new Circle(); Rollable *pRollable2 = dynamic_cast<Rollable*>(pShape2);//pRollable不爲NULL
指針比較編譯
接上面的例子,在個人機器上pShape2
和pRollable2
的值(所指向的地址)分別爲: pShape2: 0x0039A294
, pRollable2:0x0039A290
ast
說明dynamic_cast
在進行轉型的時候對不一樣多態類型設置了不一樣的偏移量。接下來的問題是 pRollable2 == pShape2