zoukankan      html  css  js  c++  java
  • 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
    -------------------

    参考

  • 相关阅读:
    将Web项目War包部署到Tomcat服务器基本步骤(完整版)
    性能实战分析-环境搭建(一)
    SQL Server Profiler追踪数据库死锁
    性能测试的各种监控工具大全
    python学习
    Linux常见面试题一
    Linux下用于查看系统当前登录用户信息的4种方法
    HDU 1394 Minimum Inversion Number(线段树求逆序对)
    SGU 180 Inversions(离散化 + 线段树求逆序对)
    Codeforces Round #FF (Div. 2) C. DZY Loves Sequences
  • 原文地址:https://www.cnblogs.com/noluye/p/14402934.html
Copyright © 2011-2022 走看看