1. static_cast在c++中類似於c中的強制類型轉換
2.dynamic_cast, C++提供了dynamic_cast函數用於動態轉型,相比C風格的強制類型轉換和C++ reinterpret_cast,dynamic_cast提供了類型安全檢查,所以在多態類型間進行轉換更提倡采用dynamic_cast。
基本用法
dynamic_cast可以獲取目標對象的引用或指針:
1 T1 obj; 2 3 T2* pObj = dynamic_cast<T2*>(&obj);//轉換為T2指針,失敗返回NULL 4 5 T2& refObj = dynamic_cast<T2&>(obj);//轉換為T2引用,失敗拋出bad_cast異常
多態類型
在使用時需要注意:被轉換對象obj的類型T1必須是多態類型,即T1必須公有繼承自其它類,或者T1擁有虛函數(繼承或自定義)。若T1為非多態類型,使用dynamic_cast會報編譯錯誤。下面的例子說明了哪些類屬於多態類型,哪些類不是:
//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:
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
說明dynamic_cast在進行轉型的時候對不同多態類型設置了不同的偏移量。接下來的問題是
pRollable2 == pShape2
這個表達式應該返回什么呢?答案是:1,即指針比較相等。也許從C語言轉到C++的朋友可能會感到困惑,因為在C語言中指針的比較只是值比較而已。顯然,對於多態類型,C++編譯器為==運算符做了更多的幕后工作來保證指針比較注重對象的同一性而非指針的值。至於實現細節涉及到C++對象模型,這是我還不甚熟悉的內容,故本文不再深入。