MFC中的运行时类型识别(第二篇)

     按照Frame3中的图(3-1)“类别型录”网,要实现 IsKindOf功能,再轻松不过了。

MFC中的运行时类型识别(第二篇)_第1张图片

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

   // in header file

class CObject

{

public:

   ...

   BOOL IsKindOf(const CRuntimeClass* pClass) const;

};

//in implementation file

BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const //类型识别
{
CRuntimeClass* pClassThis = GetRuntimeClass();
while (pClassThis!=NULL)
{
if (pClassThis == pClass)
{
return TRUE;
}
pClassThis = pClassThis->m_pBaseClass;
}
return FALSE;
}

    注意,while循环中所追踪的是“同宗”路线,也就是凭借着 m_pBaseClass而非m_pNextClass。假设我们调用的是:

 CView* pView = new CView;

 pView->IsKingOf(RUNTIME_CLASS(CWINAPP));

    IsKindOf 的参数其实就是 &CWinApp::classCWinApp。函数内利用GetRuntimeClass先取得 &CView::classCView,然后循线而上(从图3-1来看,所谓的循线分别是CView、CWnd、CCmdTarget、CObject),每获得一个 CRuntimeClass对象指针,就拿来和 CView::classCView的指针比较。依照此思路,就完成了 IsKindOf函数。

2)IsKindOf的使用方式如下:

       CMyDoc* pMyDoc = new CMyDoc;
CMyView* pMyView = new CMyView;
CWnd* pMyWnd = pApp->m_pMainWnd;

cout<<pMyDoc->IsKindOf(RUNTIME_CLASS(CMyDoc))<<"\n";               //为true
cout<<pMyDoc->IsKindOf(RUNTIME_CLASS(CDocument))<<"\n";  //为true
cout<<pMyDoc->IsKindOf(RUNTIME_CLASS(CCmdTarget))<<"\n"; //为true
cout<<pMyDoc->IsKindOf(RUNTIME_CLASS(CObject))<<"\n";     //为true
cout<<pMyDoc->IsKindOf(RUNTIME_CLASS(CWinApp))<<"\n";  //为false
cout<<pMyDoc->IsKindOf(RUNTIME_CLASS(CView))<<"\n\n";    //为false


cout<<pMyView->IsKindOf(RUNTIME_CLASS(CView))<<"\n";  //为true
cout<<pMyView->IsKindOf(RUNTIME_CLASS(CObject))<<"\n";  //为true
cout<<pMyView->IsKindOf(RUNTIME_CLASS(CWnd))<<"\n";    //为true
cout<<pMyView->IsKindOf(RUNTIME_CLASS(CFrameWnd))<<"\n\n";   //为false

cout<<pMyWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd))<<"\n";  //为true
cout<<pMyWnd->IsKindOf(RUNTIME_CLASS(CWnd))<<"\n";     //为true
cout<<pMyWnd->IsKindOf(RUNTIME_CLASS(CObject))<<"\n";  //为true
cout<<"pMyWnd->IsKindOf(RUNTIME_CLASS(CDocument))<<"\n";   //为false

   详细代码,请看工程Frame4。

效果如下:


        图(2)“类型识别”的结果

//mfc.h

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

#include <iostream.h>

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;

        // 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 _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)

class CObject
{
public:
  CObject::CObject()  {
                      }
  CObject::~CObject() {
                      }

  virtual CRuntimeClass* GetRuntimeClass() const;
  BOOL IsKindOf(const CRuntimeClass* pClass) const;

public:
  static CRuntimeClass classCObject;
};

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_DYNAMIC(CWnd)
public:
  CWnd::CWnd()   {
                 }
  CWnd::~CWnd()  {
                 }

  virtual BOOL Create();
  BOOL CreateEx();
  virtual BOOL PreCreateWindow();
};

class CFrameWnd : public CWnd
{
        DECLARE_DYNAMIC(CFrameWnd)
public:
  CFrameWnd::CFrameWnd()   {
                           }
  CFrameWnd::~CFrameWnd()  {
                           }
  BOOL Create();
  virtual BOOL PreCreateWindow();
};

class CView : public CWnd
{
        DECLARE_DYNAMIC(CView)
public:
  CView::CView()   {
                   }
  CView::~CView()  {
                   }
};


// global function
CWinApp* AfxGetApp();

//mfc.cpp

#include "my.h"

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

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

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

IMPLEMENT_DYNAMIC(CCmdTarget,CObject)
IMPLEMENT_DYNAMIC(CWinThread,CCmdTarget)
IMPLEMENT_DYNAMIC(CWinApp,CWinThread)
IMPLEMENT_DYNAMIC(CWnd,CCmdTarget) //其实在MFC中此句是,IMPLEMENT_DYNCREATE()
IMPLEMENT_DYNAMIC(CFrameWnd,CWnd)  //其实在MFC中此句是,IMPLEMENT_DYNCREATE()
IMPLEMENT_DYNAMIC(CDocument,CCmdTarget)
IMPLEMENT_DYNAMIC(CView,CWnd)

//global function
CWinApp* AfxGetApp()
{
	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_DYNAMIC(CMyFrameWnd)
public:
	CMyFrameWnd();
	~CMyFrameWnd(){}
};

class CMyDoc:public CDocument
{
	DECLARE_DYNAMIC(CMyDoc)
public:
	CMyDoc::CMyDoc(){}
	CMyDoc::~CMyDoc(){}
};

class CMyView:public CView
{
	DECLARE_DYNAMIC(CMyView)
public:
	CMyView::CMyView(){}
	CMyView::~CMyView(){}
};

//global function
void PrintAllClasses();


//my.cpp

#include "my.h"

CMyWinApp theApp;

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

CMyFrameWnd::CMyFrameWnd()
{
	Create();
}

//宏的实现
IMPLEMENT_DYNAMIC(CMyFrameWnd,CFrameWnd) //在MFC中,此语句是,IMPLEMENT_DYNCREATE(CMyFrameWnd,CFrameWnd)
IMPLEMENT_DYNAMIC(CMyDoc,CDocument) //在MFC中,此语句是,IMPLEMENT_DYNCREATE(CMyDoc,CDocument)
IMPLEMENT_DYNAMIC(CMyView,CView) //在MFC中,此语句是,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";
	}
}

void main()
{
	CWinApp* pApp = AfxGetApp();
	
	pApp->InitApplication();
	pApp->InitInstance();
	pApp->Run();
	
	//PrintAllClasses();
	CMyDoc* pMyDoc = new CMyDoc;
	CMyView* pMyView = new CMyView;
	CWnd* pMyWnd = pApp->m_pMainWnd;

	cout<<"pMyDoc->IsKindOf(RUNTIME_CLASS(CMyDoc))  "<<pMyDoc->IsKindOf(RUNTIME_CLASS(CMyDoc))<<"\n";
	cout<<"pMyDoc->IsKindOf(RUNTIME_CLASS(CDocument)) "<<pMyDoc->IsKindOf(RUNTIME_CLASS(CDocument))<<"\n";
	cout<<"pMyDoc->IsKindOf(RUNTIME_CLASS(CCmdTarget)) "<<pMyDoc->IsKindOf(RUNTIME_CLASS(CCmdTarget))<<"\n";
	cout<<"pMyDoc->IsKindOf(RUNTIME_CLASS(CObject))  "<<pMyDoc->IsKindOf(RUNTIME_CLASS(CObject))<<"\n";
	cout<<"pMyDoc->IsKindOf(RUNTIME_CLASS(CWinApp)) "<<pMyDoc->IsKindOf(RUNTIME_CLASS(CWinApp))<<"\n";
	cout<<"pMyDoc->IsKindOf(RUNTIME_CLASS(CView)) "<<pMyDoc->IsKindOf(RUNTIME_CLASS(CView))<<"\n\n";

	cout<<"pMyView->IsKindOf(RUNTIME_CLASS(CView)) "<<pMyView->IsKindOf(RUNTIME_CLASS(CView))<<"\n";
	cout<<"pMyView->IsKindOf(RUNTIME_CLASS(CObject)) "<<pMyView->IsKindOf(RUNTIME_CLASS(CObject))<<"\n";
	cout<<"pMyView->IsKindOf(RUNTIME_CLASS(CWnd)) "<<pMyView->IsKindOf(RUNTIME_CLASS(CWnd))<<"\n";
	cout<<"pMyView->IsKindOf(RUNTIME_CLASS(CFrameWnd)) "<<pMyView->IsKindOf(RUNTIME_CLASS(CFrameWnd))<<"\n\n";
	
	cout<<"pMyWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)) "<<pMyWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd))<<"\n";
	cout<<"pMyWnd->IsKindOf(RUNTIME_CLASS(CWnd)) "<<pMyWnd->IsKindOf(RUNTIME_CLASS(CWnd))<<"\n";
	cout<<"pMyWnd->IsKindOf(RUNTIME_CLASS(CObject)) "<<pMyWnd->IsKindOf(RUNTIME_CLASS(CObject))<<"\n";
	cout<<"pMyWnd->IsKindOf(RUNTIME_CLASS(CDocument)) "<<pMyWnd->IsKindOf(RUNTIME_CLASS(CDocument))<<"\n";

}


你可能感兴趣的:(C++,mfc,MTTI)