zoukankan      html  css  js  c++  java
  • c++中RTTI

      RTTI 是“Runtime Type Information”的缩写,意思是:运行时类型信息。它提供了运行时确定对象类型的方法。本文将简略介绍 RTTI 的一些背景知识、描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI;本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和 dynamic_cast。如何确定对象的动态类型呢?答案是使用内建的 RTTI 中的运算符:typeid 和 dynamic_cast。

      typeid的主要作用就是让用户知道当前的变量是什么类型的,对于我们自定义的结构体和类,tpyeid都能支持。

     typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用,它的表达式有下图两种形式。

    如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作(在之后的章节中我会来分析type_info类文件的源码):

     t1 == t2  如果两个对象t1和t2类型相同,则返回true;否则返回false
     t1 != t2  如果两个对象t1和t2类型不同,则返回true;否则返回false
     t.name()  返回类型的C-style字符串,类型名字用系统相关的方法产生
     t1.before(t2)  返回指出t1是否出现在t2之前的bool值
    #include <iostream>
    using namespace std;

    class Base {};
    class Derived: public Base {};

    int main()
    {
        Base b, *pb;
        pb = NULL;
        Derived d;

        cout << typeid(int).name() << endl
             << typeid(unsigned).name() << endl
             << typeid(long).name() << endl
             << typeid(unsigned long).name() << endl
             << typeid(char).name() << endl
             << typeid(unsigned char).name() << endl
             << typeid(float).name() << endl
             << typeid(double).name() << endl
             << typeid(string).name() << endl
             << typeid(Base).name() << endl
             << typeid(b).name()<<endl
             << typeid(pb).name()<<endl
             << typeid(Derived).name() << endl
             << typeid(d).name()<<endl
             << typeid(type_info).name() << endl;
             
        return 0;
    }

     运行结果:

    dynamic_cast 操作符,将基类的指针或引用安全的转换为派生类的指针或引用
    1. 原理:将一个基类对象指针(或引用)cast (抛)到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。

    2. 返回值:对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。 

    3. 注意:dynamic_cast在将父类cast到子类时,父类必须要有虚函数。
    在c++中使用dynamic_cast进行类型转换属于向下类型,即将基类类型转换为派生类类型,向上类型转换编译器可以自动完成。
    下面的代码说明了C++中RTTI运行机制。
    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    class base
    {
    public:
    
       virtual  void funA() {cout<<"Base "<<endl;}
    };
    
    class derived : public base
    {
    public:
        virtual  void funB() {  cout<<"derived "<<endl;}
    };
    
    void funcC(base* p)
    {
        derived* dp=dynamic_cast<derived*>(p);
        if(dp!=NULL)
            dp->funB();
        else
            p->funA();
    
    }
    
    void funcD(base* p)
    {
        derived* dp=NULL;
        if(typeid(*p)==typeid(derived))
        {
            dp=static_cast<derived*>(p);
            dp->funB();
        }
        else
            p->funA();
    
    }
    
    int main()
    {
    
        base *cp=new derived;//向上类型转换,系统自动完成,指针cp指向derived中继承base部分
        cout<<typeid(cp).name()<<endl;//class base*
        cout<<typeid(*cp).name()<<endl;//class derived
        funcD(cp); //typeid(*cp)==typeid(derived),使用static_cast<derived*>(cp)也可以将基类转换为派生类,是在编译时完成,而dynamic_cast是在运行时处理的
        funcC(cp);//采用dynamic_cast完成基类到派生类的转换,转换成功
        base* dp=new base;
        funcC(dp);//基类指针指向基类,此时采用dynamic_cast完成基类到派生类的转换失败。
    funcD(dp); return 0; }

    运行结果为:

    class base*
    class derived
    class derived
    class derived
    class base
    class base

    注意:基类指针或引用指向派生类对象的情况,此时转换才有意义。 否则转换就不能成功,如上面的funcC(dp)函数中derived* dp=dynamic_cast<derived*>(dp)就失败了,返回NULL

     
     
  • 相关阅读:
    css3——box-sizing属性
    HTML5存储--离线存储
    微信公众号爆出前端安全漏洞
    Js获取宽高度的归纳集锦总结
    Yii 2 修改 URL 模式为 PATH 模式,并隐藏index.php
    SQL 查询优化 索引优化
    linux提示语言包
    安装linux工作环境
    linux常用命令
    PHP解决抢购、秒杀、抢楼、抽奖等阻塞式高并发库存防控超量的思路方法
  • 原文地址:https://www.cnblogs.com/xiaodingmu/p/7351888.html
Copyright © 2011-2022 走看看