C++中的dynamic_cast

dynamic_cast 是一种 C++ 风格的类型转换。它加入了一些验证的机制,更像是一种运行时的函数。

它的应用场景是沿着类的层次结构,安全地转换指针或引用。

例如,对于基类 Base,有两个继承 Base 的类 A 和类 B。类 A 和类 B 的实例可以很容易地用 Base 类型变量 a 和 b 来存储,但是此时要将 a 和 b 转换为 A 类型或者 B 类型却不是显然的,因为编译器并不知道这个 Base 类型的变量 a 或 b,究竟装的是 A 类还是 B 类。

因此需要在运行时判断父类的实际类型信息,这个信息称为运行时类型信息(RunTime Type Information, RTTI),通常在 Visual Studio、Xcode 中是默认打开的。dynamic_cast 就是利用了 RTTI,并且加入了额外的验证功能。RTTI 和 dynamic_cast 验证都会带来性能上的额外成本。 

使用 dynamic_cast 必须要求基类至少有一个虚函数,使得该类是多态的。

class Base
{
public:
    virtual void f() {}  // must be polymorphic to use runtime-checked dynamic_cast
};

创建两个继承基类的类 A 和类 B:

class A : public Base
{
public:
    void f()
    {
        std::cout << "A's behavior" << std::endl;
    }
};

class B : public Base
{
    void f()
    {
        std::cout << "B's behavior" << std::endl;
    }
};

下面的用例分别代表了:

  • 将 Base 类指针(由 A 类指针转换而来)转换为 A 类指针;
  • 将 Base 类引用(由 A 类引用转换而来)转换为 A 类引用;  
  • 将 Base 类指针(由 B 类指针转换而来)转换为 A 类指针;
  • 将 Base 类引用(由 B 类引用转换而来)转换为 A 类引用。

当指针转换失败时,返回的是空指针;当引用转换失败时,会抛出异常。

 1 #include <iostream>
 2 
 3 class Base
 4 {
 5 public:
 6     virtual void f() {}  // must be polymorphic to use runtime-checked dynamic_cast
 7 };
 8 
 9 class A : public Base
10 {
11 public:
12     void f()
13     {
14         std::cout << "A's behavior" << std::endl;
15     }
16 };
17 
18 class B : public Base
19 {
20     void f()
21     {
22         std::cout << "B's behavior" << std::endl;
23     }
24 };
25 
26 int main() {
27     Base* baseA1 = new A;
28     Base& baseA2 = *baseA1;
29     Base* baseB1 = new B;
30     Base& baseB2 = *baseB1;
31 
32     // downcast for pointer
33     if (A* a = dynamic_cast<A*>(baseA1))
34     {
35         a->f();
36     }
37     else
38     {
39         std::cout << "Not the right A type!" << std::endl;
40     }
41     std::cout << "-------------------" << std::endl;
42 
43     // downcast for reference
44     try {
45         A& a = dynamic_cast<A&>(baseA2);
46         a.f();
47     } catch(const std::bad_cast& e)
48     {
49         std::cout << e.what() << std::endl;
50     }
51     std::cout << "-------------------" << std::endl;
52 
53     // sidecast for pointer
54     if (A* a = dynamic_cast<A*>(baseB1))
55     {
56         a->f();
57     }
58     else
59     {
60         std::cout << "Not the right A type!" << std::endl;
61     }
62     std::cout << "-------------------" << std::endl;
63 
64     // sidecast for reference
65     try {
66         A& a = dynamic_cast<A&>(baseB2);
67         a.f();
68     } catch(const std::bad_cast& e)
69     {
70         std::cout << e.what() << std::endl;
71     }
72     std::cout << "-------------------" << std::endl;
73 
74     delete baseA1;
75     delete baseB1;
76     return 0;
77 }

该程序会输出:

A's behavior
-------------------
A's behavior
-------------------
Not the right A type!
-------------------
std::bad_cast
-------------------

参考

原文地址:https://www.cnblogs.com/noluye/p/14402934.html