宏定义中#和##及DECLARE_DYNAMIC / IMPLEMENT_DYNAMIC宏

#

告诉编译器,将它后面字符串进行stringfication;

##

告诉编译器,将两个字符串系在一起组成一个新的字符串;

看了这个就理解了:

#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) 
    static char _lpsz##class_name[] = #class_name;  // static char _lpszCView[] = "CView";
  ...

注:这是宏定义中,编译器的行为。

顺便,以最近的一个项目代码为例解释一下DECLARE_DYNAMIC / IMPLEMENT_DYNAMIC宏

  • LiInspectorDlg.h
class CLiInspectorDlg:public CDialog{
    DECLARE_DYNAMIC(CLiInspectorDlg)  // 1.
public:
    ...
};
  • LiInspectorDlg.cpp
#include "LiInspectorDlg.h"
...

IMPLEMENT_DYNAMIC(CLiInspectorDlg, CDialog)  // 2.
...
...

先看头文件:

把DECLARE_DYNAMIC(CLiInspectorDlg)宏声明展开为:

class CLiInspectorDlg:public CDialog{
public:
    static CRuntimeClass classCLiInspectorDlg; 
    virtual CRuntimeClass* GetRuntimeClass() const;
public:
    ...
};

接着看源文件:

把IMPLEMENT_DYNAMIC(CLiInspectorDlg, CDialog)宏声明展开为:

static char _lpszCLiInspectorDlg[] = "CLiInspectorDlg";
CRuntimeClass CLiInspectorDlg::classCLiInspectorDlg = { 
    _lpszCLiInspectorDlg, sizeof(CLiInspectorDlg), 0xFFFF, NULL, 
    &CDialog::classCDialog, NULL };
static AFX_CLASSINIT _init_CLiInspectorDlg(&CLiInspectorDlg::classCLiInspectorDlg);
CRuntimeClass* CLiInspectorDlg::classCLiInspectorDlg() const { 
    return &CLiInspectorDlg::classCLiInspectorDlg; }

另外,AFX_CLASSINIT是一个struct,它负责类别型录网的link工作。。。它有一个构造函数为:

// declare
struct AFX_CLASSINIT{
    AFX_CLASSINIT(CRuntimeClass* pNewClass); 
};
// implement
AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass){ 
    pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
    CRuntimeClass::pFirstClass = pNewClass;
}

  

 


 

写给自己:

SimRTTI的仿真代码

个人总结:

  • 全局变量的内存分配,先于main;
  • new运算符,引发construction函数;
  • 类别型录网由simple list建立,它的顺序取决于IMPLEMENT_DYNAMIC(class_name, base_class_name)的顺序,class_name决定了list的节点元素;
  • sizeof空类也会占用4byte的,不然还不用内存呀,哼想的美。。。。相关知识看其它笔记吧;
  • new引发的construction函数,如果没有delete与之对应,在vs2013编译器中未追踪到destruction函数;

只看到这些destruction函数的运行,他们是对应于全局变量的;那么,new对应的呢?没找到。。

附上construction函数的运行;

 

注:可查看代码的不同版本来追溯回忆当时的思路

 


 

IsKindOf功能仿真:

  • 添加了IsKindOf接口函数,由于错误定义了_IMPLEMENT_RUNTIMECLASS造成IsKindOf函数死循环;
  • 另外,添加的new和delete来观察construction函数和destruction函数的动作;

个人总结:

  • IsKindOf功能的实现,依赖于base_class_name;类别型录的建立连接,依赖于AFX_CLASSINIT和class_name;
  • static相关(看其它笔记):宏定义中的static变量和函数的实现,只有初始化时执行一次;局部static和全局static的区别;
  • new,如果有delete对应,会引发destruction;如果没有,程序退出时触发destruction;
  • 注意IMPLEMENT_DYNAMIC的触发时间;

最后,注意一下这几个函数的位置:Create()、CreateEx()、Run()、PreCreateWindow()、InitInstance()、InitApplication();以及m_pMainWnd和m_pCurrentWinApp。

原文地址:https://www.cnblogs.com/xiawuhao2013/p/10083639.html