zoukankan      html  css  js  c++  java
  • RTTI(运行时类型识别)

      运行时类型识别(Run-time type identification , RTTI),是指在只有一个指向基类的指针或引用时,确定所指对象的准确类型的操作。其常被说成是C++的四大扩展之一(其他三个为异常、模板和名字空间)。

    使用RTTI的两种方法:

      1、typeid()

      第一种就像sizeof(),它看上像一个函数,但实际上它是由编译器实现的。typeid()带有一个参数,它可以是一个对象引用或指针,返回全局typeinfo类的常量对象的一个引用。可以用运算符“= =”和“!=”来互相比较这些对象,也可以用name()来获得类型的名称。如果想知道一个指针所指对象的精确类型,我们必须逆向引用这个指针。比如:

    #include <typeinfo>
    #include <iostream>
    #include <cmath>
    using namespace std;
    class Shape
    {
    public :
        int area(float r)
        {
            float s=3.14*pow(r,2);
            return s;
        }
    };
    int main()
    {  
        Shape* shape=new Shape;
        cout<< typeid(*shape).name()<<endl;
        system("pause");
    }

      运行结果为:

      为了保持一致性,typeid()也可以用于内部类型,所以下面的表达式结果为true:

    typeid(36) == typeid(int)
    typeid(0) == typeid(int)
    
    int i;
    typeid(i) == typeid(int)
    typeid(&i) ==typeid(int*)

      可以用typeid 检查基本类型和非多态类型

    //可以用typeid 检查基本类型和非多态类型: 
    #include <typeinfo>
    #include <iostream>
    using namespace std;
    typedef  unsigned int UINT ;
    int main()
    {  
        cout<< typeid(UINT).name()<<endl;
        cout<< typeid(string).name()<<endl;
        system("pause");
    }

      运行结果如图所示:

      用typeid分析指针与引用的区别

    #include <typeinfo>
    #include <iostream>
    using namespace std;
    class B
    {   
    public:  
        virtual double fun() 
        { 
            return 0.1; 
        }   
    };
    class D :public B   
    {
    };
    int main()
    {   
        B *p = new D;    
        B &r = *p;    //无名对象照样有别名
        cout<<(typeid(p)==typeid(B*)); //仅指向子类中父类部分
        cout<<(typeid(p)!=typeid(D*));  //而非指向整个子类对象
        cout<<(typeid(r)==typeid(D));   //引用的类型却是子类的
        cout<<(typeid(*p)==typeid(D)); //间址访问的是子类对象
        cout<<(typeid(*p)!=typeid(B));  //而非父类
        cout<<(typeid(&r)==typeid(B*)); //引用的地址是父类的
        cout<<(typeid(&r)!=typeid(D*));  //而非子类的
        system("pause");
        return 0;
    }

      运行结果:

      2、dynamic_cast <type-id> (expression)

      该运算符把expression转换成type-id类型的对象。Type-id 必须是类的指针、类的引用或者void*,不可是对象;如果 type-id 是类指针类型,那么expression也必须是一个指针,如果 type-id 是一个引用,那么 expression 也必须是一个引用。
      dynamic_cast主要用于类层次间的上行转换下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_caststatic_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
    #include <typeinfo>
    #include <iostream>
    using namespace std;
    class Shape
    {
    public:
        virtual void Draw()
        {
        }
    };
    class Circle:public Shape
    {
    public:
        virtual void Draw()
        {
        }
    };
    int main()
    {  
        Shape* sp=new Circle;
        Circle* cp=dynamic_cast<Circle*>(sp);
        if(cp)  
            cout<<"cast successful"<<endl;;
        system("pause");
    }

      运行结果:

    如何使用RTTI:

    • 先激活RTTI;
    • 对象所属类型必须是多态类族
    • 若使用dynamic_cast<>转换一个引用,则要使用异常处理机制,因为它可能抛出 std::bad_cast异常;当使用dynamic_cast<>运算符转换一个指针时,定要检查结果是否为NULL
    • 若使用typeid (*p)来检索对象的类型信息,又恰碰 p == NULL时,将抛出std::bad_typeid异常;
  • 相关阅读:
    CCF NOI1062 计算曼哈顿距离
    CCF NOI1061 Wifi密码
    CCF NOI1073 放苹果
    CCF NOI1072 爬楼梯
    CCF NOI1071 Pell数列
    CCF NOI1064 计算斐波那契第n项
    NOI训练行动路线图
    CCF NOI1060 雷同检测
    CCF NOI1059 表达式求值
    CCF NOI1057 石头剪刀布
  • 原文地址:https://www.cnblogs.com/gaohongchen01/p/4085908.html
Copyright © 2011-2022 走看看