《深入浅出MFC》系列之动态创建

时间:2022-07-14 05:45:58

/*********************************************************************************************************************
*   发布日期:2017-11-13 16:23:44
*   进度:
*   作者:LuoTian
*   备注:动态创建
*********************************************************************************************************************/

这一篇承接上一篇的运行时类型识别,当各个类像链表一样串接之后,做各种功能就比较简单。

动态创建的思路:

动态创建就是指输入一个类名就能创建一个对象,比如在控制台中输入Base,就能创建Base类的对象。

假设有三个类Base,B,C,继承关系为Base<-B<-C,其中Base为根类。根据上一篇所写,将这三个类通过CRuntimeClass进行串接。因为动态创建需要这个,原因容易理解,假如你输入一个Base,程序则必须根据输入的这个字符串在链接的类中查找是否存在Base这个类,于是就需要遍历,从C开始一直查找到Base。

为了实现这些功能,除了在CRuntimeClass里面再添加一些信息之外,还在能动态创建的类中添加一个静态函数CreateObject( );

流程如下:

假定输入Base,程序根据pFirst从尾端开始遍历各个类,查找是否有类名=Base的类,如果不存在则程序返回。如果存在,再看它的一个字段m_pfnCreateObject是否为空,而这个m_pfnCreateObject是一个函数指针,所指向的就是在能动态创建的类中添加的静态函数CreateObject(),假如一个类不能动态创建,那么肯定没有这个CreateObject函数,则在初始化CRuntimeClass的时候,m_pfnCreateObject也就为NULL了,如果能动态创建,m_pfnCreateObject就指向了CreateObject( ),然后通过m_pfnCreateObject指针执行函数调用。

思路总结:

一、能动态创建的类中有CreateObject()函数。
二、能动态创建的类的CRuntimeClass结构中的m_pfnCreateObject字段初赋值为CreateObjec,如果为NULL,则不具备动态创建的能力。

//实现比较简单,直接new一个对象返回;
static Base * PASCAL CreateObject(){return new B;}

示例代码如下:

#include <iostream>
using namespace std;
#define PASCAL _stdcall
class Base;

/***************核心的CRuntimeClass结构********************/
struct CRuntimeClass
{
    char * name;    //类名
    int ClassSize;    //类大小;
    Base *(PASCAL * m_pfnCreateObject)();
    CRuntimeClass *pBase;//基类的CRuntimeClass地址

    Base * CreateObject();
    static CRuntimeClass * PASCAL Load();
    static CRuntimeClass *pFirst;
    CRuntimeClass *pNext;
};
CRuntimeClass * CRuntimeClass::pFirst=NULL;//pFirst初始化为空;

CRuntimeClass* PASCAL CRuntimeClass::Load()
{
    char szClassName[64];
    CRuntimeClass* pClass;
    cout << "输入需要动态创建的类名:";
    cin >> szClassName;

    //在各个类的CRuntimeClass结构中查找是否存在输入的类名
    for (pClass = pFirst; pClass != NULL; pClass = pClass->pNext)
    {
        if (strcmp(szClassName, pClass->name) == 0)
            return pClass;
    }
    cout<<"没有找到该类名,程序退出!!"<<endl;
    return NULL;
}
Base * CRuntimeClass::CreateObject()
{

    if (m_pfnCreateObject == NULL)
    {
        cout<<"不能动态创建!!"<<endl;
        return NULL;
    }
    else
    {
        Base * pObject =(*m_pfnCreateObject)();    
        return pObject;
    }
}
//****************结束*****************************************/

struct AFX_CLASSINIT
{
    AFX_CLASSINIT(CRuntimeClass *pNewClass)
    {
        pNewClass->pNext=CRuntimeClass::pFirst;
        CRuntimeClass::pFirst=pNewClass;
    }
};

class Base //根基类;
{
public:
    static CRuntimeClass classBase;
    virtual CRuntimeClass * GetRuntimeClass()const
    {
        return &Base::classBase;
    }
    virtual void SayHello()
    {
        cout<<"基类Base的SayHello"<<endl;
    }
};

class B:public Base //B类
{
public:
    static CRuntimeClass classB;
    static Base * PASCAL CreateObject(){return new B;}
    virtual CRuntimeClass * GetRuntimeClass()const{
        return &B::classB;
    }
    virtual void SayHello(){ cout<<"类B的SayHello,动态创建对象成功!!"<<endl;}
};

class C:public B //C类
{
public:
    static CRuntimeClass classC;
    virtual CRuntimeClass * GetRuntimeClass()const{
        return &C::classC;
    }
};

//***********************实现部分*************************//

struct CRuntimeClass Base::classBase={"Base",sizeof(Base),NULL,NULL};
static AFX_CLASSINIT _init_A(&Base::classBase);//

struct CRuntimeClass B::classB={"B",sizeof(B),B::CreateObject,&Base::classBase,};
static AFX_CLASSINIT _init_B(&B::classB);//


struct CRuntimeClass C::classC={"C",sizeof(C),NULL,&B::classB,};
static AFX_CLASSINIT _init_C(&C::classC);//


int main(int argc,char *argv[])
{
    CRuntimeClass * pClassRef;
    Base *pOb;
    cout<<"共有三个类Base,B,C,其中B类具有动态创建能力... ."<<endl;
    while(true)
    {
        if((pClassRef=CRuntimeClass::Load())==NULL)
            break;
        pOb=pClassRef->CreateObject();
        if(pOb!=NULL)
            pOb->SayHello();
    }
    return 0;
}