• C++运行时动态类型


    RTTI

    运行时类型识别(RTTI)的引入有三个作用:

    1. 配合typeid操作符的实现;
    2. 实现异常处理中catch的匹配过程;
    3. 实现动态类型转换dynamic_cast

    typeid操作符的实现

    静态类型

    C++中支持使用typeid关键字获取对象类型信息,它的返回值类型是const std::type_info&,例

    #include <typeinfo>
    #include <cassert>
    struct B {} b, c;
    struct D : B {} d;
    void test() {
        const std::type_info& tb = typeid(b); 
        const std::type_info& tc = typeid(c); 
        const std::type_info& td = typeid(d);
        assert(tb == tc);   // b和c具有相同的类型
        assert(&tb == &tc); // tb和tc引用的是相同的对象
        assert(tb != td);   // 虽然D是B的子类,但是b和d的类型却不同
        assert(&tb != &td); // tb和td引用的是不同的对象
    }
    

    动态类型

    当typeid的操作数引用的是一个动态类(含有虚函数的类) 类型时,它的返回值是被引用对象对应类型的const std::type_info&,例:

    #include <typeinfo>
    #include <cassert>
    struct B { virtual void foo() {} };
    struct C { virtual void bar() {} };
    struct D : B, C {};
    void test() {
        D d;
        B& rb = d;
        C& rc = d;
        assert(typeid(rb) == typeid(d));  // rb引用的类型与d相同
        assert(typeid(rb) == typeid(rc)); // rb引用的类型与rc引用的类型相同
    }
    

    编译时可能还不知道rb或rc引用的类型,运行时怎么能判断该返回基类还是派生类对应的类型信息对象呢?

    首先我们看看虚表的结构,在虚函数指针前面有RTTI信息。

    image

    如果是含有虚函数,运行时便可以通过vptr找到“虚函数表”,而“虚函数表”之前的一个位置存放了需要的类型信息对象,typeid可以直接返回这里的类型信息对象引用即可。

    image

    实现异常处理中catch的匹配过程

    catch的匹配过程也可利用与typeid相似的原理进行类型匹配判断,此不再赘述。

    动态类型转换(dynamic_cast)

    先上一个例子:

    image

    type_info对象里面会有整个继承体系的信息(通过指针),因此继承关系可以通过此树状结构判断,有了继承关系,再递归从虚表中查找基类子对象在派生类中的偏移值,便可以确定最终返回地址。

    image

    • '# 4例子:
      通过pa找到_D的type_info,对比和C的type_info的不同,但是在type_info的指针里面找到C的type_info。加上C的type_info的通过偏移量,返回指针结果
    • '# 2例子:
      通过pa找到D的type_info,和目标D的type_info相同,直接加上偏移量,返回指针

    参考文献

    C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理

  • 相关阅读:
    深入探讨 Python 的 import 机制:实现远程导入模块
    PEP8中文版 -- Python编码风格指南
    【转】python---方法解析顺序MRO(Method Resolution Order)<以及解决类中super方法>
    【转】Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128)
    Python字典的json格式化处理(换行与不换行)
    最详细的CentOS 6与7对比(三):性能测试对比
    最详细的CentOS 6与7对比(二):服务管理对比
    WEBAPI 自动生成帮助文档
    MEF IOC使用
    MVC分页示例
  • 原文地址:https://www.cnblogs.com/biterror/p/6909569.html
Copyright © 2020-2023  润新知