Dynamic Creation

MFC.h

#define BOOL int
#define TRUE 1
#define FALSE 0
#define LPCSTR LPSTR
typedef char* LPSTR;
#define UINT int
#define PASCAL _stdcall
#define TRACE1 printf

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

class CObject;

struct CRuntimeClass
{
	// Attributes
	LPCSTR m_lpszClassName;
	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 simple list
	static CRuntimeClass* pFirstClass; // start of class list
	CRuntimeClass* m_pNextClass; // linked list of registered classes
};

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_DYNAMIC(class_name) \
static CObject* PASCAL CreateObject();
#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
static char _lpsz##class_name[] = #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 SayHello() { 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() {
 m_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() {
 cout << "CWnd Constructor \n";

}
 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() {
 cout << "CFrameWnd Constructor \n";

}
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();
MY.h
#include <iostream>
#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() {
 cout << "CMyDoc Constructor \n";

}
 CMyDoc::~CMyDoc() {

}
 void SayHello() { cout << "Hello CMyDoc \n"; }
 };

 class CMyView : public CView
 {
DECLARE_DYNCREATE(CMyView)
public:
CMyView::CMyView() {
cout << "CMyView Constructor \n";

}
CMyView::~CMyView() {

}
void SayHello() { cout << "Hello CMyView \n"; }
};

// global function
 void AfxPrintAllClasses();
MFC.CPP
#include "my.h" // it should be mfc.h, but for CMyWinApp definition, so...

extern CMyWinApp theApp;

static char szCObject[] = "CObject";
 struct CRuntimeClass CObject::classCObject =
{ szCObject, sizeof(CObject), 0xffff, 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_SERIAL: %hs.\n",
m_lpszClassName);
return NULL;
}

CObject* pObject = NULL;
pObject = (*m_pfnCreateObject)();

return pObject;

}

CRuntimeClass* PASCAL CRuntimeClass::Load()
{
 char szClassName[64];
CRuntimeClass* pClass;
// JJHOU : instead of Load from file, we Load from cin.
 cout << "enter a class name... ";
 cin >> szClassName;

 for (pClass = pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
 {
 if (strcmp(szClassName, pClass->m_lpszClassName) == 0)
 return pClass;
 }

 TRACE1("Error: Class not found: %s \n", szClassName);
 return NULL; // not found
 }

CRuntimeClass* CObject::GetRuntimeClass() const
 {
return &CObject::classCObject;
}

 BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
 CRuntimeClass* pClassThis = GetRuntimeClass();
 while (pClassThis != NULL)
 {
if (pClassThis == pClass)
 return TRUE;
 pClassThis = pClassThis->m_pBaseClass;
 }
 return FALSE; // walked to the top, no match
}

 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;
}

CWinApp* AfxGetApp()
{
 return theApp.m_pCurrentWinApp;
 }

IMPLEMENT_DYNAMIC(CCmdTarget, CObject)
IMPLEMENT_DYNAMIC(CWinThread, CCmdTarget)
IMPLEMENT_DYNAMIC(CWinApp, CWinThread)
IMPLEMENT_DYNAMIC(CDocument, CCmdTarget)
IMPLEMENT_DYNCREATE(CWnd, CCmdTarget)
IMPLEMENT_DYNAMIC(CView, CWnd)
IMPLEMENT_DYNCREATE(CFrameWnd, CWnd)
MY.CPP
#include "my.h"

CMyWinApp theApp;

 BOOL CMyWinApp::InitInstance()
{
 m_pMainWnd = new CMyFrameWnd;
return TRUE;
}

 CMyFrameWnd::CMyFrameWnd()
{
cout << "CMyFrameWnd Constructor \n";
Create();
}

 IMPLEMENT_DYNCREATE(CMyFrameWnd, CFrameWnd)
 IMPLEMENT_DYNCREATE(CMyDoc, CDocument)
 IMPLEMENT_DYNCREATE(CMyView, CView)

void PrintAllClasses()
{
CRuntimeClass* pClass;

 // just walk through the simple list of registered 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();
 //Test Dynamic Creation
 CRuntimeClass* pClassRef;
 CObject* pOb;
while (1)
 {
 if ((pClassRef = CRuntimeClass::Load()) == NULL)
 break;

pOb = pClassRef->CreateObject();
 if (pOb != NULL)
 pOb->SayHello();
}

}

这里用MFC深入浅出FRAME6例子来做讲解:

首先看结果:


接下来进行解析:

CWinApp* pApp = AfxGetApp();

定义 CWinApp指针 pApp指向 AfxGetApp()的返回值theApp.m_pCurrentWinApp;

theApp.m_pCurrentWinApp;进行展开:

theApp为CMyWinApp 的对象,

CMyWinApp类结构如下:

 class CMyWinApp : public CWinApp
{
public:
CMyWinApp::CMyWinApp() {


}
 CMyWinApp::~CMyWinApp() {
 
}

由结构可以得知没有m_pCurrentWinApp;所以查找父类

父类CWinApp定义如下:

class CWinApp : public CWinThread
{
DECLARE_DYNAMIC(CWinApp)
public:
 CWinApp*
m_pCurrentWinApp;
CWnd* m_pMainWnd;
public:
 CWinApp::CWinApp() {
 m_pCurrentWinApp = this;
}
 CWinApp::~CWinApp() {
}
virtual BOOL InitApplication() {
return TRUE;
 }
virtual BOOL InitInstance() {
return TRUE;
}
virtual int Run() {
return CWinThread::Run();
}
};

由此可以知道m_pCurrentWinApp是一个CWinApp类指针;

方便了解CWinApp类先对类中DECLARE_DYNAMIC()进行扩展;

已知存在巨集#define DECLARE_DYNAMIC(class_name) \
public: \
static CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const;

DECLARE_DYNAMIC(CWinApp)=

public :\


带入CWinApp类中,得知完整定义为:

class CWinApp : public CWinThread
{
public:

static CRuntimeClass classCWinAPP;

virtuial CRuntimeClass *GetRuntimeClass() const;

 CWinApp*  m_pCurrentWinApp ;
CWnd* m_pMainWnd;
public:
 CWinApp::CWinApp() {
 m_pCurrentWinApp = this;
}
 CWinApp::~CWinApp() {
}
virtual BOOL InitApplication() {
return TRUE;
 }
virtual BOOL InitInstance() {
return TRUE;
}
virtual int Run() {
return CWinThread::Run();
}
};

ok 那么我们就知道pApp就直指向当前类CMyWinApp类父类CWinApp的一个this指针。

从而

pApp->InitApplication();
pApp->InitInstance();
pApp->Run();

所实现的就是this->InitApplication();this->InitInstance();;this->Run();

对上述函数进行展开得到的结果就是:return TRUE ; return TRUE;以及return CWinThread::Run();

然后查看CWinThread::Run();发现结果就是return 1;

这样看会不会太累了,对的~我们可以将继承关系做成一下图解:



首先看初始化过程:pApp->InitInstance();产生的结果CWnd Constructor  CFrameWnd Constructor CMyFrameWnd Constructor 从上图可以看到CWinApp 继承CWinTread类,理论上和CWnd,CFrameWnd及CMyFrameWnd八竿子打不到。

那在哪些环节可以动态关联呢?

最后可以找到以下语句:

BOOL CMyWinApp::InitInstance()
{
 m_pMainWnd = new CMyFrameWnd;
return TRUE;
}

是不是很刺激..你可以将这句话//就会发现不再产生结果CWnd Constructor  CFrameWnd Constructor CMyFrameWnd Constructor ,居然CMyFrameWnd出现了,对应CWnd->CFrameWnd->CMyFrameWnd的家族体系就牵引而出,那么又有一个问题,CMyWinApp可是CWinApp的派生类呀~CWinApp指向的可是CMyWinApp的父类InitInstance(),然后探索会发现:

CWinApp* pApp = AfxGetApp();

CWinApp* AfxGetApp()
{
 return
theApp.m_pCurrentWinApp;
 }

CMyWinApp theApp;

 m_pCurrentWinApp = this;

原来折腾半天 pApp指向的是派生类的this....这个弯绕的有点大~不过总算是出来了;


然后进入CRuntimeClass::Load()环节..这个就是找到类属于我们这个体系,不多说

然后进入pOb = pClassRef->CreateObject();

这个的本质是查看类中是否存在DECLARE_DYNCREATE(class_name)聚集,存在该巨集的类都是可以动态生成的。

所以输入CObject和 CView类的时候会出现m_pfnCreateObject==NULL的现象因为,无DECLARE_DYNCREATE也就无

自身的static CObject* PASCAL CreateObject();从而为空也在预料之中。

猜你喜欢

转载自blog.csdn.net/iloveyou418/article/details/79079057
今日推荐