~$ 存档

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

/*********************************************************************************
*   发布日期: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;

posted on 2017-11-13 14:03  LuoTian  阅读(416)  评论(0编辑  收藏  举报