美文网首页
浅谈RTTI

浅谈RTTI

作者: 404Not_Found | 来源:发表于2021-09-11 12:17 被阅读0次
    • 作者: 雪山肥鱼
    • 时间:20210912 11:41
    • 目的: 了解RTTI

    何为RTTI

    class Base
    {
    public:
        virtual void f()
        {
            cout << "Base::f()" << endl;
        }
        virtual void g()
        {
            cout << "Base::g()" << endl;
        }
        virtual void h()
        {
            cout << "Base::h()" << endl;
        }
    
        virtual  ~Base()
        {
    
        }
    };
    
    class Derive :public Base
    {
    public:
        virtual void g()
        {
            cout << "Derive::g()" << endl;
        }
        void mySelfFunc()
        {
    
        }
        virtual ~Derive()
        {
    
        }
    };
    
    int main(int argc, char **argv)
    {
        Base *pb = new Derive();
        pb->g();
    
        Derive mydrive;
        Base &yb = mydrive;
        yb.g();
    
        //c++ 运行时类型识别 RTTI,父类中必须有虚函数,父类中无虚函数,则RTTI 无意义。
        //RTTI 可以在执行期间查询一个多态指针,或者多态引用的信息
        //RTTI 可以靠 typeid 和 dynamic_cast 运算符体现
        
        cout << typeid(*pb).name() << endl;// class::deirve
        cout << typeid(yb).name() << endl; // class::derive
    
        Derive *pderive = dynamic_cast<Derive*>(pb);
        if (pderive != NULL)
        {
            cout << "pb 实际是一个 derive* 类型" << endl;
            pderive->mySelfFunc();
        }
    
        return 0;
    }
    

    RTTI,运行时类型识别。实现的要求就是必须存在虚函数,也就是说一定要有虚函数表。
    没有虚表,则RTII毫无意义啦
    RTTI 可以在执行期间查询一个多态指针或者多态引用的信息
    RTTI 体现在 :

    • typeid(指针/引用).name()
    • dynamic_cast<Class>(Point/Ref)

    RTTI与type_info

    typieid(P/R)返回的是一个常量对象的引用,这个对象的类型是 type_info, 对象的所有信息存在于 type_info 这个类中。

    class Base
    {
    public:
        virtual void f()
        {
            cout << "Base::f()" << endl;
        }
        virtual void g()
        {
            cout << "Base::g()" << endl;
        }
        virtual void h()
        {
            cout << "Base::h()" << endl;
        }
    
        virtual  ~Base()
        {
    
        }
    };
    
    class Derive :public Base
    {
    public:
        virtual void g()
        {
            cout << "Derive::g()" << endl;
        }
        void mySelfFunc()
        {
    
        }
        virtual ~Derive()
        {
    
        }
    };
    
    int main(int argc, char **argv)
    {
        Base *pb = new Derive();
        pb->g();
    
        Derive mydrive;
        Base &yb = mydrive;
        yb.g();
        
        //RTTI 实现原理
        // typeid 返回的是一个常量对象的引用,这个对象类的信息多存在于 type_info这个类中
        const type_info &tp = typeid(*pb);
    
        //只能读,不能写
        Base *pb2 = new Derive();
        const type_info &tp2 = typeid(*pb2);
        if (tp == tp2)
        {
            cout << "same class type" << endl;
        }
    
        //其他用法:
            //静态类型
        cout << typeid(int).name() << endl;
        cout << typeid(Base).name() << endl;
        cout << typeid(Derive).name() << endl;
        Derive *pb3 = new Derive();
        cout << typeid(pb3).name() << endl;
    
        //动态:
        cout << typeid(*pb).name() << endl;//class Derive
        cout << typeid(yb).name() << endl;//class Derive
        Base * pb4 = new Derive();
        const type_info &tp3 = typeid(*pb4);
    
        return 0;
    }
    

    静态: 常规类型 与 不带多态的类型判断
    动态: 引入多态后, 可以判断出父类指针所指向的对象是子类. 自动识别多态,多继承中也能识别出指向的子类

    如果没有虚函数,则全是 class Base,RTTI失效,就是指针的静态类型

    typeinfo 保存位置

    const std::type_info &tp2 = typeid(*pb2);
    
    eax, dwrod ptr [pb2]
    eax
    __RTtypeid(010A158Ch)
    esp, 4
    dword ptr [tp2], eax
    

    对应的汇编代码,重点看下 __RTtypeid,仅在虚函数表出现的情况,才有这个东东。

    typeinfo保存位置.png

    rtti相关信息在虚函数往上的4个字节。

    点到为止,了解到这里就够了。

    vptr,vtbl,rtti的type info 构造时机

    除了vptr 是运行时子对象的构造函数中生成的,其他都是编译后就存在的,只要不重新编译生成项目,地址不变

    相关文章

      网友评论

          本文标题:浅谈RTTI

          本文链接:https://www.haomeiwen.com/subject/hgozwltx.html