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

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

《深入浅出MFC》系列之运行时类型识别(RTTI)-LMLPHP

04-24 01:01