zoukankan      html  css  js  c++  java
  • 《深入浅出MFC》系列之动态创建

    /*********************************************************************************************************************
    *   发布日期: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;
    }
  • 相关阅读:
    VS2005调试网站时不显示Flash元素
    js中使用弹出窗体
    Ipod Touch/Iphone歌词同步软件整理
    Chrome Dev 4.0.*增加flash支持
    字符串数组排序(qsort参数 比较函数)
    查找两个已经排好序的数组的第k大的元素
    求用1,2,5这三个数不同个数组合的和为100的组合个数
    Hadoop分布式环境下的数据抽样(转)
    Reservoir Sampling
    欧拉回路
  • 原文地址:https://www.cnblogs.com/tinaluo/p/7826678.html
Copyright © 2011-2022 走看看