• 深入浅出mfc学习笔记——六大关键技术之仿真_运行时和动态创建


    1:PS88:MFC的类层次结构

    <1>CObject

    <2>CCmdTarget,CDocument

    <3>CCmdTarget_CWinThread_CWinApp

    CCmdTarget_CWnd_CView

    CCmdTarget_CWnd_CFrameWnd

    C++规定,全局对象的构建将比程序进入点更早。所以theApp的构造函数将更早与main。

    2:RTTI(运行时类型识别)

    编译时需选用/GR选项——包含typeinfo.h——使用新的typeid运算符,我希望我的类库具备iskindof的能力,能在执行期侦测某个对象时候属于某种类并传回 True或False。

    要达到RTTI的能力。我们的类设计者一定要在类建构起来的时候。记录必要的信息。以建立型录,型录中的类信息。以链表的方式连接起来。方便一一比较。

    以CRuntimeClass结构体描述之,其中至少需要类名称。链表的Next指针,以及链表的First指针。由于first 指针属于全局变量。所以它应该以static修饰。

    struct CRuntimeClass

    {

    LPCSTR m_lpszClassName;

    int m_nObjectsize

    CRuntimeClass* m_pBaseClass;

    Static CRuntimeClass* pFirstClass;

    CRuntimeclass * m_pNextClass;

    };

    我希望每个类都能拥有这样一个CRuntimeClass成员变量。

    为了能把CRuntimeClass对象赛到类之中,并声明一个可以抓到该对象地址的函数。我们定义Declare_dynamic宏。

    出现在宏定义中的##说明将两个字符串串在一起。

    为了各个CRunTimeClass对象的内容指定以及连接工作使用Implement_Dynamic宏来完成。

    #define Implement_Dynamic(class name,base_class name)\_Implement_RuntimeClass(Class_name,base_class_name,0xffff,NULL)

    //in .h

    class Cview:public Cwnd

    {

        Declare_dynamic(CView)

    }

    //in implementation file

    IMPlement_dynmaic(CView,Cwnd)

    链表的头总是需要特别处理。所以我们的类根源CObject不能使用上面的宏。

    Iskindof(类型识别)

    为CObject加上一个iskindof 函数,于是此函数将被所有类继承它将把参数所指定的某个CRuntimeClass对象拿来与类别型录中的元素一一比较,比较成功(在型录中发现),就传回TRUE。否则传回False

    3:Dynamic creation(动态创建)

    如果我能够把类的大小记录在类别型录中。把建构函数(即将出现的CRuntimeClass::CreateObject)也记录在类别型录中。当程序在执行器获得一个类名称,它就可以在类别型录网中找出对应的元素,然后调用其建构函数,产生出对象。

    类的对象记录在类别型录中。建构函数也记录在类别型录中。当程序在执行期间获得一个类名称,它就可以在类别型录网中找出对应的元素。然后调用其建构函数产生对象。

    CRuntimeClass中多了CObject* CreateObject();

    static CRuntimeClass *PASCAL load();

    为了适应这新增的两个宏。添加新宏Declare_dyncreate和Implement_dyncreate,从宏的定义中我们可以看到有用动态创建能力的类库必然也拥有运行时类型识别能力,因为_dyncreate宏覆盖了_dynamic宏。

    在.h中Declare_dyncreate(CFramewnd);在,cpp中implement_dyncreate(CWnd,CCmdTarget)

    总结下:

    当知道一个类名,去判断有没有这个类时,即进行类型识别,这时就是去找这个链表的过程。

    当需要动态创建时,仅仅是在CRuntimeClasss结构体增加了根据类型new 类对象的函数,在定义类类型时,类中的CRuntimeClasss成员也进行了这个类对象的创建,并保存了对象指针。

    下面是csdn中一个网友提供的解释。供为参考。

    在   #define   IMPLEMENT_DYNCREATE(class_name,base_class_name)CObject*PASCAL   class_name::CreateObject(){return   new   class_name;}\     这句是CreateObject   的定义
    时可以在编译时确定的
    一个类有一份自己函数的代码编译为二进制机器指令
    如有   IMPLEMENT_DYNCREATE(A,   baseA)
    就是   return   new   A;   它是在编译时确定的
    再有   IMPLEMENT_DYNCREATE(B,   baseB)
    就有另外一个确定的函数   return   new   B;
    注意   不是
    f(param)
    {  
          return   new(Patam)
    }
    现在的模板可以实现这一功能
    template <class   T>
    T*   new()
    {
            return   new   T;
    }
    以前的MFC是用宏来实现的   让编译器帮你写代码
    int   *p=new   int[10];
    if(p!=NULL)
    {
            AfxMessageBox( "!=NULL ");
            ASSERT(p==NULL);
    }


    #include   <iostream.h>
    #define   PASCAL   _stdcall
    class   CObject;
    #define   IMPLEMENT_DYNCREATE(class_name,base_class_name)new   class_name;


    class   CObject
    {
    public:
    void   f()
    {
    cout   < <   "I   am   here! "   < <   endl;
    }
    };
    class   CCmdTarget:   public   CObject
    {  
    public:
    static   CObject*   CreateObject();

    };
    int   main()
    {
    CObject*   pCObject   =   IMPLEMENT_DYNCREATE(   CCmdTarget,   CObject   )
    pCObject   -> f();
    return   0;
    }
    如果用new的话,你需要做的是一堆判断,形式上复杂,而且没有办法全部枚举出来。
    而dynamic   creation,实际上是形成了一个链表。你只要知道类的名字,就能在链表中找到声称这个类的一个对象的方法(代码)。我做的点简化。
    struct   DynamicCreationList
    {
    char*   className
    char*   pCodeToCreateAnObject;
    DynamicCreationList*   pNext;
    }
    这样你就能根据一个字符串(就是类的名字)来动态创建一个类的对象了。
    声明了   DECLARE_DYNCREATE   后,一个类就强制性地在列表中加入了一项。
    如果,用   new   来创建的话,很难实现动态。
    你必须知道所有的类,然后用if   (   inputClass   ==   "class1 ")等等一大堆的判断才能实现动态创建。
    要动态创建一个类对象,有如下几个步骤
    1.类说明中使用DECLARE_DYNCREATE(CLASSNMAE)宏;和在类的实现文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏;这个宏完成构造CRuntimeClass对象,并加入到链表中。

    2、使用时先通过宏RUNTIME_CLASS得到类的RunTime信息,当获得一个类名时,先用类别型录网判别这个类是否是链表中有的类,若是,就使用CRuntimeClass的成员函数CreateObject创建一个该类的实例。
    3、CObject* pObject = pRuntimeClass->CreateObject();//完成动态创建

    CRuntimeClass *pClassRef;

    CObject* pOb;

    while(1)

    {

      if((pClassRef=CRuntimeClass::load())==NULL)

         break;

    pOb= pClassRef->CreateObject();

    if(pob!=NULL)

       pob->SayHello();

    }

    参考网页

    http://www.pcdog.com/edu/vc/2005/12/g057056.html

    http://hi.baidu.com/282535629/blog/item/6e59aec2defc2a3de5dd3bd5.html

    http://www.ieing.cn/html-31903-1.html

    http://hi.baidu.com/1005301774/blog/item/bd61b19173b7f887a877a445.html

  • 相关阅读:
    【Leetcode】【Medium】Group Anagrams
    【Leetcode】【Hard】Merge k Sorted Lists
    面向.Net程序员的Sql版本管理
    分享改进 完全定制自己的代码生成器
    面向.Net程序员的后端性能优化实战
    一个winform带你玩转rabbitMQ
    vs多项目模板及add-in开发
    面向.Net程序员的前端优化
    面向.Net程序员的dump分析
    【网络安全】(一) 0成本添加访问级监控
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1760035.html
Copyright © 2020-2023  润新知