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

结果

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

这是一本讲述vc的经典书籍,对您一定会有很大的帮助的,这是第二版,后面没有续篇了,还停留在VC++5.0,现在都6.0很久了,不过确实是VC经典书刊了。 第一篇提出学习MFC程序设计之前的必要基础,包括Widnows程序的基本观念以及C++的高阶议题。“学前基础”是相当主观的认定,不过,甚于我个人的学习经验以及教学经验,我的挑选应该颇具说服力。第二篇介绍Visual C++整合环境开发工具。本篇只不过是提纲挈领而已,并不企图取代 Visual C++使用手册。然而对于软件使用的老手,此篇或已足以让您掌握Visual C++整合环境。工具的使用虽然谈不上学问,但在视觉化软件开发过程中扮演极重角色,切莫小觑它。 第三篇介绍application framework的观念,以及MFC骨乾程序,所谓骨乾程序,是指Visual C++的工具AppWizard所产生出来的程序码。当然,AppWizard会根据你的选项做出不同的程序码,我所据以解说的,是大众化选项下的产品。 第四篇以微软公司附于Visual C++光碟片上的一个范例程序Scribble为主轴,一步一步加上新的功能。并在其间深入介绍Runtime Type Information(RTTI)、Dynamic Creation、Persistence(Serialization)、Message Mapping、Command Routing等核心技术。这些技术正是其他书籍最缺乏的部分。此篇之最后数章则脱离Scribble程序,另成一格。想学习vc++的人可以好好看看!推荐大家同时看看thinking in c++,也很不错! 本书是学习MFC不可多得一本好书。 对MFC的讲解从基本原理到三大聚集的概念及使用,通过对一个个小程序的详解,让你了解利用MFC进行程式设计的来龙去脉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值