C++Primer第十九章的動態類型轉換部分講的不是很清楚,於是自己查cpp的官方手冊總結一下。
dynamic_cast < new-type > ( expression )
動態類型轉換是可以安全的在繼承體系將指針和引用進行向上、向下和橫向的轉換。其表達式的類型為運行時的動態類型。具體功能如下:
一、和隱式轉換,靜態轉換static_cast一樣的功能
1、增加const屬性:在expression和new-type類型相同或new-type為void*時,轉換結果為expression的指針或引用。並且可以在dynamic_cast前加上const限定符實現增加const屬性。
const dynamic_cast < new-type > ( expression )
2、向上轉換upcast:和static_cast和隱式轉換一樣,dynamic_cast可以將派生類轉換為基類。
二、dynamic_cast的特殊功能
如果expression是一個指向具有多態特性的基類Base的指針或引用(靜態類型),new-type是一個指向派生類Derived對象的指針或引用,具體進行哪種轉換根據expression的動態類型判斷。
1、向下轉換downcast:expression的動態類型為指向派生類Derived的指針或引用,並且Derived僅包含一份繼承自Base的對象,則轉換結果為指向Derived對象的指針或引用。(相當於從expressionh的父類轉換為子類)
2、橫向轉換sidecast:expression的動態類型為指向一個類的對象的指針或引用,該類公有繼承自Base和Derivied(Derived不一定繼承自Base)並且繼承自Derived的子成員是明確的(必須是虛繼承,不能有二義性)。則轉換結果為指向Derived的指針或引用。(相當於expression動態類型對象的一個父類轉換為另一個父類)
三、轉換失敗時如果轉換目標是指針類型則返回空指針,引用類型拋出一個bad_cast異常。
四、所謂安全是指編譯器會對dynamic_cast的對象進行類型檢查,而static_cast則不會。dynamic_cast相當於根據情況進行轉換,static_cast相當於不管情況如何強制進行轉換。
這里直接使用官方例子
1 #include <iostream> 2 3 struct V { 4 virtual void f() {} // must be polymorphic to use runtime-checked dynamic_cast 5 }; 6 struct A : virtual V {}; 7 struct B : virtual V { 8 B(V* v, A* a) { 9 // casts during construction (see the call in the constructor of D below) 10 dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B* 11 dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B 12 } 13 }; 14 struct D : A, B { 15 D() : B(static_cast<A*>(this), this) { } 16 }; 17 18 struct Base { 19 virtual ~Base() {} 20 }; 21 22 struct Derived: Base { 23 virtual void name() {} 24 }; 25 26 int main() 27 { 28 D d; // the most derived object 29 A& a = d; // upcast, dynamic_cast may be used, but unnecessary 30 [[maybe_unused]] 31 D& new_d = dynamic_cast<D&>(a); // downcast 32 [[maybe_unused]] 33 B& new_b = dynamic_cast<B&>(a); // sidecast 34 35 36 Base* b1 = new Base; 37 if(Derived* d = dynamic_cast<Derived*>(b1)) 38 { 39 std::cout << "downcast from b1 to d successful\n"; 40 d->name(); // safe to call 41 } 42 43 Base* b2 = new Derived; 44 if(Derived* d = dynamic_cast<Derived*>(b2)) 45 { 46 std::cout << "downcast from b2 to d successful\n"; 47 d->name(); // safe to call 48 } 49 50 delete b1; 51 delete b2; 52 }
輸出結果
downcast from b2 to d successful
注意:所有C++標准的轉換均產生局部變量,不實際對原變量修改。