最近研读"深入浅出mfc",有两个关于第三章的宏的问题困扰了我,请指点一二 关于CObject*(PASCAL* m_pfnCreateObject)();看到Dynamic Creation(动态生成)一节就知道了。前面的问题我没有象你一样到afx.h中找,不求甚解的就这样糊过去了。自己觉得还明白吧。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 对于上面的,我发表一下我的看法,参考一下实际上是个动态的声明(##纯粹的文字连接符)比如 对于class xxx来讲这行代码就被替换为static AFX_CLASSINIT _init_xxx(&xxx::classxxx);这就有意义了吧 下面一个还希望高手指教 第一个如gohst所说。当你做调试时,比如调试CDocument时,这个类就含有一个名为classCDocument的成员。这是用于运行时刻识别类对象类型的一种机制。第二个是一句标准格式的声明,需要你对C或C++语法中的声明的了解够深入。但一点也不可怕,这句话声明了一个函数原型,名为m_pfnCreateObject,和通常的函数申明不同的是,它是一个函数指针。(PASCAL* xxx)()将这个指针首先结合到PASCAL栈调用协定上,接着通过括号结合成一个函数指针声明。最后,这个函数指针不带参数,并且返回一个CObject*类型的对象的指针。注意到MFC的类体系基本上以CObject为依托,这个函数的功用就出来了:函数被调用后返回一个CFormView,CDocument,CMainFrame一样的对象地指针。这个指针被简化到CObject类型,但是你可以通过对象多态性正确使用这个对象指针。你也可以通过第一例的机制动态识别对象的真实类型。你也可以通过类似于DYNAMIC_DOWNCAST()《好像是这样拼写的,jy注》这样的宏动态地强制那个返回指针到确切的类型上去。 多谢几位的指点,关于##的意义我是知道的,正如gohst001(唐怕猫)所说,变为static AFX_CLASSINIT _init_xxx(&xxx::classxxx);之后,那么这个_init_xxx(&xxx::classxxx)是什么意思,在何处实现,如何调用呢?还请指点. 一定要搞懂?其实不求甚解很好的。以CDoc为例吧:class CDoc: public CDocument {...DECLARE_DYNAMIC(CDoc);};////....IMPLEMENT_DYNAMIC(CDoc, CDocument);预处理之后,上面的声明变成这个样子了:class CDoc : public CDocument{...public: static const AFX_DATA CRuntimeClass classCDoc; /* class##class_name */ virtual CRuntimeClass* GetRuntimeClass() const;};///// CObject* PASCAL CDoc::CreateObject() { return new CDoc; } IMPLEMENT_RUNTIMECLASS(CDoc, CDcoument, 0xFFFF, CDoc::CreateObject)好,预处理继续完成展开,上面的最后部分被展开为:AFX_COMDAT const AFX_DATADEF CRuntimeClass CDoc::classCDoc /* class##class_name */ = { "CDoc"/* #class_name */, sizeof(class CDoc), 0xFFFF, pfnNew, RUNTIME_CLASS(CDocument), NULL };CRuntimeClass* CDoc::GetRuntimeClass() const { return RUNTIME_CLASS(CDoc); }现在,你把它连通起来读一读吧、 抱歉:替换失误,最后一段应该是:好,预处理继续完成展开,上面的最后部分被展开为:AFX_COMDAT const AFX_DATADEF CRuntimeClass CDoc::classCDoc /* class##class_name */ = { "CDoc"/* #class_name */, sizeof(class CDoc), 0xFFFF, /*pfnNew*/CDoc::CreateObject, RUNTIME_CLASS(CDocument), NULL };CRuntimeClass* CDoc::GetRuntimeClass() const { return RUNTIME_CLASS(CDoc); } 这个RUNTIME_CLASS()有什么用处呢?这个class##class_name成员又有什么用处呢?看RUNTIME_CLASS(CDoc)展开后将会得到: ((CRuntimeClass*)(&CDoc::classCDoc)) //((CRuntimeClass*)(&class_name::class##class_name))如何,这个纽带就这么连上了。一定要去钻研这个的话,就多动手自己去做展开,多了之后就明白了。宏替换带给你便利的时候,同时给自己留下了难读难维护的后果。所以需要权衡利弊的使用宏,新流派的C++提倡用inline函数来替代 宏替换 的功能,这是其中原因之一。(不过,对于上面的情况,AFX小组的确没有选择,除了这么一个方法之外,我想不出其他的解决方法,或许,只有模板了,但模板同样的麻烦) JY,可能我还没说清楚,麻烦你再帮我解释一下:为什么使用AFX_CLASSINIT这个结构的构造函数就可以构造RTTI的链表,俄这个构造函数并没有显示执行,他与STATIC AFX_CLASSINIT _init_xxx()有什么关系?敬请指点迷津. 准确的说,这不是RTTI表。这是Afx的自行实现的动态对象识别。你还是应该查看MSDN的相关章节,例如IsKindOf()。注意到上面的"CDoc"串没有?这就是识别的依据。这是静态存储的变量(在classCDoc这个结构中),诸如IsKingOf(),STATIC_DOWNCAST()等等,基本上是在利用这个类名字的字符串进行工作。对于你说的_init_xxx,我想这是IMPLEMENT_SERIAL的一部分。这和对象的序列化存储有关。..(抱歉我要开会去了) 在dll里面如何使用exe里面的CEvent类成员变量 屏幕键盘的问题,如何重新获得当前EDIT的焦点 一个关于进程的问题. 编写一个计算成绩的小程序出现的错误!渴望得到帮助! 如何在Vc对话框中嵌入IP网络摄像机的视频图像 WSAIoctl问题 菜鸟急问dll资源问题??? 谁能给我一个《三国群侠传》的序列号吗? 100分—Win2000中的标题条 mfc使用ADO如何连接PostgreSQL查询数据库,使用以下方法查不到数据? (派分)COM/DCOM/MTS/COM+的区别?... 怎样使某个控件无效?
实际上是个动态的声明(##纯粹的文字连接符)
比如 对于class xxx来讲
这行代码就被替换为
static AFX_CLASSINIT _init_xxx(&xxx::classxxx);
这就有意义了吧
下面一个还希望高手指教
当你做调试时,比如调试CDocument时,这个类就含有一个名为classCDocument的成员。
这是用于运行时刻识别类对象类型的一种机制。第二个是一句标准格式的声明,需要你对C或C++语法中的声明的了解够深入。
但一点也不可怕,这句话声明了一个函数原型,名为m_pfnCreateObject,和通常的函数申明不同的是,它是一个函数指针。
(PASCAL* xxx)()将这个指针首先结合到PASCAL栈调用协定上,接着通过括号结合成一个函数指针声明。
最后,这个函数指针不带参数,并且返回一个CObject*类型的对象的指针。注意到MFC的类体系基本上以CObject为依托,这个函数的功用就出来了:函数被调用后返回一个CFormView,CDocument,CMainFrame一样的对象地指针。这个指针被简化到CObject类型,但是你可以通过对象多态性正确使用这个对象指针。你也可以通过第一例的机制动态识别对象的真实类型。你也可以通过类似于DYNAMIC_DOWNCAST()《好像是这样拼写的,jy注》这样的宏动态地强制那个返回指针到确切的类型上去。
变为static AFX_CLASSINIT _init_xxx(&xxx::classxxx);之后,
那么这个_init_xxx(&xxx::classxxx)是什么意思,在何处实现,如何调用呢?
还请指点.
class CDoc: public CDocument {
...
DECLARE_DYNAMIC(CDoc);
};////....
IMPLEMENT_DYNAMIC(CDoc, CDocument);预处理之后,上面的声明变成这个样子了:
class CDoc : public CDocument{
...
public:
static const AFX_DATA CRuntimeClass classCDoc; /* class##class_name */
virtual CRuntimeClass* GetRuntimeClass() const;
};/////
CObject* PASCAL CDoc::CreateObject()
{ return new CDoc; }
IMPLEMENT_RUNTIMECLASS(CDoc, CDcoument, 0xFFFF, CDoc::CreateObject)
好,预处理继续完成展开,上面的最后部分被展开为:
AFX_COMDAT const AFX_DATADEF CRuntimeClass CDoc::classCDoc /* class##class_name */ = {
"CDoc"/* #class_name */, sizeof(class CDoc), 0xFFFF, pfnNew, RUNTIME_CLASS(CDocument), NULL };
CRuntimeClass* CDoc::GetRuntimeClass() const
{ return RUNTIME_CLASS(CDoc); }
现在,你把它连通起来读一读吧、
AFX_COMDAT const AFX_DATADEF CRuntimeClass CDoc::classCDoc /* class##class_name */ = {
"CDoc"/* #class_name */, sizeof(class CDoc), 0xFFFF, /*pfnNew*/CDoc::CreateObject, RUNTIME_CLASS(CDocument), NULL };
CRuntimeClass* CDoc::GetRuntimeClass() const
{ return RUNTIME_CLASS(CDoc); }
看RUNTIME_CLASS(CDoc)展开后将会得到:
((CRuntimeClass*)(&CDoc::classCDoc))
//((CRuntimeClass*)(&class_name::class##class_name))
如何,这个纽带就这么连上了。一定要去钻研这个的话,就多动手自己去做展开,多了之后就明白了。
宏替换带给你便利的时候,同时给自己留下了难读难维护的后果。所以需要权衡利弊的使用宏,新流派的C++提倡用inline函数来替代 宏替换 的功能,这是其中原因之一。
(不过,对于上面的情况,AFX小组的确没有选择,除了这么一个方法之外,我想不出其他的解决方法,或许,只有模板了,但模板同样的麻烦)
为什么使用AFX_CLASSINIT这个结构的构造函数就可以构造RTTI的链表,
俄这个构造函数并没有显示执行,他与STATIC AFX_CLASSINIT _init_xxx()有什么关系?
敬请指点迷津.
这是Afx的自行实现的动态对象识别。你还是应该查看MSDN的相关章节,例如IsKindOf()。注意到上面的"CDoc"串没有?这就是识别的依据。这是静态存储的变量(在classCDoc这个结构中),诸如IsKingOf(),STATIC_DOWNCAST()等等,基本上是在利用这个类名字的字符串进行工作。
对于你说的_init_xxx,我想这是IMPLEMENT_SERIAL的一部分。这和对象的序列化存储有关。..
(抱歉我要开会去了)