[搬运]探察RUNTIME_CLASS之类的秘密
搬自:http://blog.sina.com.cn/s/blog_47fa4cef0100hfhz.html学mfc学到文档,视图和框架的时候,明白必需在这三个类的派生类的类声明
里加上DECLARE_DYNCREATE,然后在类声明外合适的地方加上IMPLEMENT_DYNCREA
TE,然后文档,视图和框架,还有文档模板就能够协调务工了。查看msdn,发明
类似的宏有这几对:
DECLARE_DYNAMIC 和 IMPLEMENT_DYNAMIC
DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE
DECLARE_SERIAL 和 IMPLEMENT_SERIAL
虽然msdn里介绍了她们的功能,但对于它们为啥会起那样的功能心里却没底,于是翻了翻mfc的源代码Code,喜爱钻牛角尖的人能够和我一起来钻一钻。
1。
RUNTIME_CLASS宏的定义是那样的:
#define RUNTIME_CLASS(class_name)
((CRuntimeClass*)(&class_name::class##class_name))
其中##的意思是把##两边的符号都停止宏扩展(假如它们是宏的话),然后把扩展
后的内容连接在一起,中间不加空格。例如:RUNTIME_CLASS(CView)将被扩展成
:
(CRuntimeClass*)(&CView::classCView)
但那个classCView是什么意思?原来,classCView是由DECLARE_DYNAMIC(CView)
引入的唯一public属性的CRuntimeClass类别的静态成员变量:
static const AFX_DATA CRuntimeClass classCView;
原来RUNTIME_CLASS的功能就引用由DECLARE_DYNAMIC宏引入的静态成员变
量。
2。DECLARE_DYNAMIC(class_name)
由于篇幅的理由,宏的具体定义代码Code就不列出来了,感兴趣的能够去看文档
afx.h。
该宏往类中声明了三个成员:
protected:
static CRuntimeClass* PASCAL _GetBaseClass();
public:
virtual CRuntimeClass* GetRuntimeClass() const;
static const AFX_DATA CRuntimeClass class##class_name;
有两个成员参数,唯一静态成员变量class+类名,同RUNTIME_CLASS相似,如
果是DECLARE_DYNAMIC(CView)的话,那个静态成员变量将是classCView。可见这
个成员变量的名字是和DECLARE_DYNAMIC的参数parameter有关的。在下文咱们把那个成员变
量统统记做class##class_name。
那个静态成员和两个成员参数在哪里被初始化和具体呈现呢?原来是在IMPL
EMENT_DYNAMIC宏里。
3。IMPLEMENT_DYNAMIC(class_name, base_class_name)
查看它的宏定义,假如_AFXDLL被定义了的话,由DECLARE_DYNAMIC引入的成
员的初始化和呈现是那样的:
CRuntimeClass* PASCAL class_name::_GetBaseClass()
{
return RUNTIME_CLASS(base_class_name);
}
CRuntimeClass* class_name::GetRuntimeClass() const
{
return RUNTIME_CLASS(class_name);
}
AFX_COMDAT const AFX_DATADEF
CRuntimeClass class_name::class##class_name =
{
#class_name,
sizeof(class class_name),
0xFFFF,
NULL,
NULL,
&class_name::_GetBaseClass,
NULL
};//这是在初始化静态成员变量class##class_name。
//CRuntimeClass框架的各个成员的意义可查看msdn。
4。_DECLARE_DYNAMIC(class_name)
该宏的定义和DECLARE_DYNAMIC(class_name)基本相同。不相同之处是静态成员
class##class_name前面没有const修饰符。
5。DECLARE_DYNCREATE(class_name)
该宏也往类中引入了DECLARE_DYNAMIC宏所引入的那三个成员。除此之外,它
还另外引入了唯一成员:
static CObject* PASCAL CreateObject();
该宏引入的成员在IMPLEMENT_DYNCREATE里初始化和呈现。
6。IMPLEMENT_DYNCREATE(class_name, base_class_name)
该宏自然是初始化和呈现由DECLARE_DYNCREATE引入的成员了。
咱们看看CreateObject的呈现:
CObject* PASCAL class_name::CreateObject()
{
{
return new class_name;
}
呵,那个参数是如此简单,它就用CObject类里重载的new操作符创建唯一
该类类别的对象。
7。_DECLARE_DYNCREATE(class_name)
该宏引入了和DECLARE_DYNCREATE引入的四个成员差不多的成员。唯一的区别
是该宏引入的静态成员class##class_name前面没有const修饰符。
8。DECLARE_SERIAL(class_name)
该宏引入了和_DECLARE_DYNCREATE所引入的相同的四个成员,另外它还多了
这么一句:
AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &
pOb);
原来是把重载操作符operator>>的参数当作该类的友元。于是在操作符参数oper
ator>>中就能够来访该类的成员了。
9。IMPLEMENT_SERIAL(class_name, base_class_name, wSchema)
该宏初始化了成员变量:
CRuntimeClass class_name::class##class_name=
{
#class_name,
sizeof(class class_name),
wSchema,
class_name::CreateObject),
RUNTIME_CLASS(base_class_name),
NULL
};//在那里,class##class_name前面是没有const修饰符的。
该宏还呈现了下列参数:
CObject* PASCAL class_name::CreateObject()
{
return new class_name;
}
CRuntimeClass* class_name::GetRuntimeClass() const
{
return RUNTIME_CLASS(class_name);
}
CArchive& AFXAPI operator>>
(CArchive& ar, class_name* &pOb)
{
pOb=(class_name*)ar.ReadObject(RUNTIME_CLASS(class_name));
return ar;
}
该宏还声明了唯一参数原型:
AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name));
页:
[1]