zoukankan      html  css  js  c++  java
  • 《深入浅出MFC》系列之运行时类型识别(RTTI)

    /*********************************************************************************
    *   发布日期:2017-11-13 14:01:16
    *   进度:
    *   作者:LuoTian
    *   备注:运行时类型识别
    *********************************************************************************/

    这是读《深入浅出》做的笔记,书本程序是对MFC框架的仿真,我做的是对他的程序仿真,主要为了更进一步的简化理解。

    为了简化问题,我这里只用三个类A,B,C说明问题,继承关系为A<-B<-C,即A为根基类,A派生B,B派生C,层次非常简单,现在做一下通俗的解释。

    思想:

    问题的引出是判断某类是否为某个类的派生类,比如C类明显是B的派生类,也即B为C的基类,如何让这种派生关系记录下来呢?于是采用一种直接了当的办法,在每个类中添加一个信息结构体,专门记录各种信息。
    比如,B中添加一个信息结构体,包括如下信息:

    • 我的类名是什么?->B
    • 我的基类是谁?->类A(实际为类A的信息结构体地址)
    • 我的前驱类是谁(pNext)?->类A(类A的信息结构体地址)
    • 我的类大小?->sizeof(B)

    等等,可以看出,此结构体不仅记录自身的信息,还记录和外界的相互关系。
    其中,A类是根类,所以它的基类和前驱都是NULL。

    在这个思想引导下,通过一系列操作之后,形成的形状就和链表非常相似(参看文章末尾),在此"链表"的末端有一个CRuntimeClass类型的指针pFirst,通过这个pFirst就可以到达各个类的CRuntimeClass。

    从思路中可以看出,关键部分就是安插在每个类中的结构体CRuntimeClass,而且思路也很简单。

    《深入浅出》模仿了MFC的宏实现,我这个代码是把宏解开之后进行的模仿,主要便于观察,只要用宏再包装一下就可以逆转回去。

    示例代码,功能:在ABC三个类中各安装一个CRuntimeClass并链接起来,从尾端开始遍历各个类的名字。

    #include <iostream>
    using namespace std;
    
    //CRuntimeClass结构,并初始化静态成员pFirst=NULL;
    struct CRuntimeClass
    {
        char * name;    //类名
        int ClassSize;    //类大小;
        CRuntimeClass *pBase;//基类的CRuntimeClass地址
    
        static CRuntimeClass *pFirst;
        CRuntimeClass *pNext;
    };
    CRuntimeClass * CRuntimeClass::pFirst=NULL;////****************结束******************************
    
    struct AFX_CLASSINIT
    {
        AFX_CLASSINIT(CRuntimeClass *pNewClass)
        {
            pNewClass->pNext=CRuntimeClass::pFirst;
            CRuntimeClass::pFirst=pNewClass;
        }
    };
    
    class A //根基类;
    {
    public:
        static CRuntimeClass classA;
        virtual CRuntimeClass * GetRuntimeClass()const
        {
            return &A::classA;
        }
    };
    
    class B:public A //B类
    {
    public:
        static CRuntimeClass classB;
        virtual CRuntimeClass * GetRuntimeClass()const
        {
            return &B::classB;
        }
    };
    class C:public B //C类
    {
    public:
        static CRuntimeClass classC;
        virtual CRuntimeClass * GetRuntimeClass()const
        {
            return &C::classC;
        }
    };
    
    //***********************实现部分*************************//
    
    struct CRuntimeClass A::classA={ //A类的CRuntimeClass初始化
        "classA类",
        sizeof(A),
        NULL,//根基类A由于没有基类,所以Base为NULL;
    };
    static AFX_CLASSINIT _init_A(&A::classA);//
    
    struct CRuntimeClass B::classB={ //B类的CRuntimeClass初始化
        "classB类",
        sizeof(B),
        &A::classA,
    };
    static AFX_CLASSINIT _init_B(&B::classB);//
    
    struct CRuntimeClass C::classC={ //C类的CRuntimeClass初始化
        "classC类",
        sizeof(C),
        &B::classB,
    };
    static AFX_CLASSINIT _init_C(&C::classC);//
    
    int main(int argc,char *argv[])
    {
        CRuntimeClass *p;
        for(p=CRuntimeClass::pFirst;p!=NULL;p=p->pNext)
        {
            cout<<p->name<<endl;
        }
        delete p;
        return 0;
    }

    代码运行到①时,pFirst=NULL;
    代码运行到②时,pFirst指向类A的CRuntimeClass;
    代码运行到③时,pFirst指向类B的CRuntimeClass;
    代码运行到④时,pFirst指向类C的CRuntimeClass;

  • 相关阅读:
    7年.NET面试Java的尴尬历程
    服务挂后Dump日志
    并发中如何保证缓存DB双写一致性(JAVA栗子)
    如何通过Visual Studio来管理我们的数据库项目
    无需Get更多技能,快速打造一个可持久化的任务调度
    Dapper Use For Net
    2014年——新的开始,新的人生
    途牛网站无线架构变迁实践
    windows 下解决 Time_Wait 和 CLOSE_WAIT 方法
    System.Data.DbType 与其它DbType的映射关系
  • 原文地址:https://www.cnblogs.com/tinaluo/p/7826025.html
Copyright © 2011-2022 走看看