MFC 运行时信息(侯捷MFC)

MFC 运行时信息(RTTI)

思路

运行时的信息是属于类的,将CRuntimeClass的类当做类的静态成员变量,再用指针连接整个类的继承体系,就可以得到类的运行时信息。由于代码的相似度很高,用宏定义的方法可以更方便。
这里写图片描述

CRuntimeClass定义

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)

mfc.h

#define BOOL int
#define TRUE 1
#define FALSE 0
#define LPCSTR  LPSTR
typedef char*   LPSTR;
#define UINT int
#define PASCAL _stdcall
#define NULL 0
//#include <iostream>

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()  {
        //this->
        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"  // it should be mfc.h, but for CMyWinApp definition, so...

extern CMyWinApp theApp;

CRuntimeClass* CRuntimeClass::pFirstClass = NULL;

AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)
{
    pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
    CRuntimeClass::pFirstClass = pNewClass;
}

static char szCObject[] = "CObject";

CRuntimeClass CObject::classCObject ={ szCObject, sizeof(CObject), 0xffff, NULL, NULL, NULL };

static AFX_CLASSINIT _init_CObject(&CObject::classCObject);


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)
IMPLEMENT_DYNAMIC(CFrameWnd, CWnd)
IMPLEMENT_DYNAMIC(CDocument, CCmdTarget)
IMPLEMENT_DYNAMIC(CView, CWnd)

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

my.h

//#include <iostream>
#include "mfc.h"

class CMyWinApp : public CWinApp
{
    DECLARE_DYNAMIC(CMyWinApp)
public:
    CMyWinApp::CMyWinApp()   {
    }
    CMyWinApp::~CMyWinApp()  {
    }

    virtual BOOL InitInstance();
};

class CMyFrameWnd : public CFrameWnd
{
public:
    CMyFrameWnd();
    ~CMyFrameWnd()  {
    }
};

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

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

// global function
void PrintAllClasses();

my.cpp

#include "my.h"
#include <iostream>
#include <iomanip>
using namespace std;

IMPLEMENT_DYNAMIC(CMyWinApp, CWinApp)
CMyWinApp theApp;

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

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

void PrintAllClasses()
{
    CRuntimeClass* pClass = NULL;

    cout << "_______________________________________CRuntimeClass's infromation__________________________________________\n\n";
    cout << setw(10) << "m_lpszClassName\t\tm_nObjectSize\tm_wSchema\tm_pfnCreateObject\tm_pBaseClass\tm_pNextClass\n";

    // just walk through the simple list of registered classes
    for (pClass = CRuntimeClass::pFirstClass; pClass != NULL;
        pClass = pClass->m_pNextClass)
    {
        cout << setw(15) << pClass->m_lpszClassName << "\t";
        cout << setw(15) << pClass->m_nObjectSize << "\t";
        cout << setw(15) << pClass->m_wSchema << "\t";
        cout << setw(20) << pClass->m_pfnCreateObject << "\t";
        cout << setw(20) << pClass->m_pBaseClass << "\t";
        cout << setw(10) << pClass->m_pNextClass << "\t";
        cout << setw(10) << " address " << pClass << "\n";
    }
    cout << "链表头指针为 " << CRuntimeClass::pFirstClass << endl;
}
//------------------------------------------------------------------
// main
//------------------------------------------------------------------
void main()
{
    CWinApp* pApp = AfxGetApp();

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

    PrintAllClasses();


    cout << "______________RTTI______________" << "\n";
    cout << pApp->IsKindOf(RUNTIME_CLASS(CMyWinApp)) << endl;
    cout << pApp->IsKindOf(RUNTIME_CLASS(CWinApp)) << endl;
    cout << pApp->IsKindOf(RUNTIME_CLASS(CWinThread)) << endl;
    cout << pApp->IsKindOf(RUNTIME_CLASS(CCmdTarget)) << endl;
    cout << pApp->IsKindOf(RUNTIME_CLASS(CObject)) << endl;
    cout << pApp->IsKindOf(RUNTIME_CLASS(CWnd)) << endl;
}
//------------------------------------------------------------------

结果

这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/xiaolixi199311/article/details/81296106
MFC