#
告诉编译器,将它后面字符串进行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;
}
写给自己:
个人总结:
- 全局变量的内存分配,先于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。