现在的位置: 首页 > 综合 > 正文

MFC深入浅出–动态创建

2013年12月09日 ⁄ 综合 ⁄ 共 8323字 ⁄ 字号 评论关闭
 

Dynamic Creation(动态创建)
 程序执行期间,根据动态获得一个类名称,要求程序产生一个对象。“类别型录网”为此提供了基础。如果能够把类的大小记录在类别型录中,把建构函数(不是C++的构造函数,而是指即将出现的CRuntimeClass::CreateObject())也记录在类别型录中,当程序在执行期获得一个类名称,它就可以在“类别型录网”中找出对应的元素,然后调用其建构函数,产生出对象。
类别型录网的元素CRuntimeClass于是发生变化:
Struct CruntimeClass
{
 //Attributes
    LRCSTR m_lpnzClassName;
    Int m_nObjectSize;
UINT m_wSchema; //schema number of the loaded class
CObject *(PASCAL * m_pfnCreateObject)();//NULL=>abstract class
CRuntimeClass *m_pBaseClass;
CObject *CreateObject();
Static CRuntimeClass *PASCAL Load();
//CruntimeClass objects linked together in the simple list
static CRuntimeClass *pFirstClass;
CRuntimeClass * m_pNextClass;
};
 
DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE宏
 为了适应CRuntimeClass中新增的成员变量,再新添加两个宏。DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE:
#define DECLARE_DYNCREATE(class_name) /
        DECLARE_DYNAMIC(class_name) /
        Static CObject *PASCAL CreateObject();
#define IMPLEMENT_DYNCREATE(class_name, base_class_name) /
        CObject *PASCAL class_name::CreateObject() /
{ return new class_name; }/
_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,/
class_name::CreateObject)
以CframeWnd为例,程序如下:
class CframeWnd : public CWnd
{
    DECLARE_DTNCREATE(CFrameWnd);
   
};
IMPLEMENT_DYNCREATE(CframeWnd,CWnd)
展开如下:
class CframeWnd : public CWnd
{
 public:
    static CRuntimeClass ClassCFrameWnd;
    virtual CRuntimeClass *GetRuntimeClass() const;
    static CObject *PASCAL CreateObject();
   
};
CObject *PASCAL CframeWnd;;CreateObject()
{   return new CframeWnd; }
static char _lpszCFrameWnd[] = CFrameWnd;
CRuntimeClass CframeWnd::classCFrameWnd = { _lpszCFrameWnd,sizeof(CFrameWnd),
           0XFFFF,CframeWnd::CreateObject,RUNTIME_CLASS(CWnd),NULL };
static AFX_CLASSINIT _init_CframeWnd(&CframeWnd::classCFrameWnd);
CRuntimeClass * CframeWnd::GetRuntimeClass() const
{ return &CframeWnd::classCFrameWnd;}
从宏的定义可以清楚的看到,拥有动态创建(Dynamic Creation)能力的类库,必然拥有RTTI能力.因为_DYNCREATE宏覆盖了_DYNAMIC宏.
 
范例程序
MFC.H
#define BOOL int
#define TURE 1
#define FALSE 0
#define LPCSTR LPSTR
#define char * LPSTR;
#define UINT int
#define PASCAL _stdcall
#define TRACE1 printf
#include <iostream.h>
#include <stdio.h>
#include <string.h>
class CObject
Struct CruntimeClass
{
 //Attributes
    LRCSTR m_lpnzClassName;
    Int m_nObjectSize;
UINT m_wSchema; //schema number of the loaded class
CObject *(PASCAL * m_pfnCreateObject)();//NULL=>abstract class
CRuntimeClass *m_pBaseClass;
CObject * CreateObject();
Static CRuntimeClass *PASCAL Load();
//CruntimeClass objects linked together in the simple list
static CRuntimeClass *pFirstClass;
CRuntimeClass * m_pNextClass;
}
Struct AFX_CLASSINIT
{ AFX_CLASSINIT(CRuntimeClass *pNewClass);};
#define RUNTIME_CLASS(class_name) /
        (&class_name::class##class_name)
#define DECLARE_DYNAMIC(class_name) /
public: /
static CRuntimeClass class##class_name; /
virtual CRuntimeClass * GetRuntimeClass() const;
#define DECLARE_DYNCREATE(class_name) /
        DECLARE_DYNAMTIC(class_name) /
        Static CObject *PASCAL CreateObject();
#define _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew) /
        static char lpsz##classname[] = #class_name; /
        CRuntimeClass class_name::class##class_name = ( /
        lpsz##class_name ,sizeof(class_name),wSchema,pfnNew,/
        RUNTIME_CLASS(base_class_name),NULL);/
        Static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name);/
        CRuntimeClass * class_name::GetRuntimeClass() const /
        {return &class_name::class##class_name;}/
#define IMPLEMENT_DYNAMIC(class_name , base_class_name) /
        _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL)
#define IMPLEMENT_DYNCREATE(class_name,base_class_name)/
        CObject *PASCAL class_name::CreateObject() /
        { return new class_name; } /
        _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0XFFFF,/
class_name::CreateObject)
class CObject
{
 public:
    CObject::CObject() { }
CObject::~CObject() { }
Virtual CRuntimeClass *GetRuntimeClass() const;
BOOL IsKindOf(const CRuntimeClass *pCLass) const;
 Public:
    static CRuntimeClass classCObject;
    virtual void Sayhell() {cout<<Hello CObject/n;}
};
class CCmdTarget : public CObject
{
 DECLARE_DYNAMIC(CCmdTarget)
 public:
    CCmdTarget:: CCmdTarget () { }
    CCmdTarget::~CCmdTarget () { }
};
class CwinThread : public CCmdTarget
{
 DECLARE_DYNAMIC(CWinThread)
 public:
    CwinThread:: CwinThread () { }
    CwinThread::~ CwinThread () { }
    Virtual BOOL InitInstance(){
Return TRUE;
}
virtual int Run(){
return 1;
}
};
class CWnd;
class CWinApp : public CwinThread
{
 DECLARE_DYNAMIC(CWinApp)
 public:
    CWinApp * m_pCurrentWinApp;
    CWnd * m_pMainWnd;
 Public:
    CWinApp::CWinApp() { pCurrentWinApp = this ;}
    CWinApp::~CWinApp() { }
    virtual BOOl InitApplication () {
      Return TRUE;
    }
    virtual BOOL InitInstance () {
       return TRUE;
    }
    virtual int Run () {
       return CWinThread::Run();
    }
};
Class CDocument : public CCmdTarget
{
 DECLARE_DYNAMIC(CDocument)
 public:
    Cdocument:: Cdocument() { }
    Cdocument::~ Cdocument() { }
};
Class CWnd : public CCmdTarget
{
 DECLARE_DYNCREATE(CWnd)
 public:
    CWnd:: CWnd () { }
CWnd::~CWnd () { }
Virtual BOOL Create();
BOOL CreateEx();
virtual BOOL PreCreateWindow();
void SayHello() {cout<<Hello CWnd/n;}
};
Class CFrameWnd : public CWnd
{
 DECLARE_DYNCREATE(CFrameWnd)
 public:
    CFrameWnd:: CFrameWnd () { }
    CFrameWnd::~CFrameWnd () { }
    BOOL Create ();
    Virtual BOOL PreCreateWindow();
void SayHello() {cout<<Hello CFrameWnd/n;}
 
};
Class CView : public CWnd
{
DECLARE_DYNAMIC(CView)
 public:
    CView:: CView () { }
    CView::~ CView () { }
};
//global function
CWinApp *AfxGetApp();
 
 
MFC.CPP
#include my.h //本该包含mfc.h,但为了CmyWinapp的定义
extern CmyWinApp theApp ; //external global object
static char szCObject[] = CObject;
struct CRuntimeClass CObject::classCObject =
    {szCObject,sizeof( CObject),0XFFFF,NULL,NULL,NULL };
static AFX_CLASSINIT _init_CObject(&CObject::classCObject);
CRuntimeClass *CRuntimeClass::pFirstClass = NULL;
AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass * pNewClass)
{
    pNewClass->m_pNextclass=CRuntimeClass ::pFirstClass;
    CRuntimeClass::pFirstClass = pNewClass;
}
CObject *CRuntimeClass::CreateObject()
{
 if(m_pfnCreateObject == NULL )
    {
        TRACE1(Error:Trying to create object which is not DECLARE_DYNCREATE nor
DECLARE_DYNAMIC:%hs./n,m_lpsClassName);
        Return NULL;
}
CObject *pObject = NULL;
PObject = (*m_pfnCreateObject)();
Return pObject;
}
CRuntimeClass *PASCAL CRuntimeClass::Load()
{
    char szClassName[64];
    CRuntimeClass *pClass;
cout<<enter a class name…”;
    cin>>szClassName;
    for(pClass=pFirstClass;pClass!=NULL;pClass=pClass)
    {
        if(strcmp(szClassName,pClass->m_lpszClassName)==0)
           return pClass;
}
TRACE1(Erroe:class not found:%s /n,szClassName);
Return NULL;
}
CRuntimeClass *CObject::GetRuntimeClass() const
{
    return &CObject::classCObject;
}
 
BOOL CWnd::Create()
{
    return TRUE;
}
BOOL CWnd::CreateEx()
{
    PreCreateWindow();
    return TRUE;
}
BOOL CWnd::PreCreateWindow()
{
    return TRUE;
}
BOOL CframeWnd::Create()
{
    CreateEx();
    return TRUE;
}
BOOL CframeWnd::PreCreateWindow()
{
    return TRUE;
}
INPLEMENT_DYNAMIC(CcmdTarget,CObject)
INPLEMENT_DYNAMIC(CWinThread, CcmdTarget)
INPLEMENT_DYNAMIC(CWinAPP, CWinThread)
INPLEMENT_DYNAMIC(CWnd,CCmdTarget)
INPLEMENT_DYNCREATE(CFrameWnd, CWnd)
INPLEMENT_DYNAMIC(CDocument, CcmdTarget)
INPLEMENT_ DYNCREATE(CView,CWnd)
//global function
CWinApp * AfxApp()
{
 return theApp.m_pCurrentWinApp;
}
 
MY.H
#include <iostream.h>
#include mfc.h
class CmyWinApp : public CWinApp
{
 public:
    CmyWinApp:: CmyWinApp() { }
    CmyWinApp::~ CmyWinApp() { }
    virtual BOOL InitInstance();
};
class CMyFrameWnd : public CframeWnd
{
    DECLARE_DYNCREATE(CMyFrameWnd)
 public:
    CMyFrameWnd();
~CMyFrameWnd() {}
void SayHello() {cout<<Hello CmyFrameWnd/n;}
};
class CmyDoc : public Cdocument
{
    DECLARE_DYNCREATE(CMyDoc)
 public:
    CmyDoc:: CmyDoc() { }
    CmyDoc::~ CmyDoc() { }
void SayHello() {cout<<Hello CMyDoc/n;}
};
class CMyView : public CView
{
    DECLARE_DYNCREATE(CMyView)
 public:
   CMyView:: CMyView () { }
    CMyView::~ CMyView () { }
void SayHello() {cout<<Hello CMyView/n;}
};
//global function
coid PrintAllClasses()
 
MFC.CPP
#include my.h
CmyWinApp theApp; //global object
BOOL CMyWinAPP::InitInstance()
{
    m_pMainWnd = new CmyFrameWnd;
    return TRUE;
}
CmyFrameWnd::CmyFrameWnd()
{
    Create();
}
IMPLEMENT_DYNCREATE(CmyFrameWnd,CFrameWnd)
IMPLEMENT_DYNCREATE(CMyDoc,CDocument)
IMPLEMENT_DYNCREATE(CMyView,CView)
void PrintAllClasses()
{
    CRuntimeClass *pClass;
    //just walk through the simple list of regidtered classes
    for(pClass = CRuntimeClass::pFirstClass;pClass!=NULL;
pClass = pCLass->m_pNextClass)
    {
        cout<<pClass->m_lpszClassName<</n;
cout<<pClass->m_nObjectSize<</n;
cout<<pClass->m_wSchema<</n;
}
}
//main()
void main()
{
    CwinApp *pApp = AfxGetApp();
    pApp->InitApplication();
    pApp->InitInstance();
pApp->Run();
   CRuntimeClass *pClassRef;
CObject *pObj;
While(1)
{
        if((pClassRef=CRuntimeClass::Load())==NULL)
           break;
pObj = pClassRef->CreateObject();
if(pObj!=NULL)
    pObj->SayHello();
}
}
 

 

抱歉!评论已关闭.