天天看點

動态類型轉換dynamic_cast

  

  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異常。

  這裡直接使用官方例子

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