关于CObject*(PASCAL* m_pfnCreateObject)();看到Dynamic Creation(动态生成)一节就知道了。
前面的问题我没有象你一样到afx.h中找,不求甚解的就这样糊过去了。自己觉得还明白吧。

解决方案 »

  1.   

    对于上面的,我发表一下我的看法,参考一下
    实际上是个动态的声明(##纯粹的文字连接符)
    比如 对于class xxx来讲
    这行代码就被替换为
    static AFX_CLASSINIT _init_xxx(&xxx::classxxx);
    这就有意义了吧 
    下面一个还希望高手指教 
      

  2.   

    第一个如gohst所说。
    当你做调试时,比如调试CDocument时,这个类就含有一个名为classCDocument的成员。
    这是用于运行时刻识别类对象类型的一种机制。第二个是一句标准格式的声明,需要你对C或C++语法中的声明的了解够深入。
    但一点也不可怕,这句话声明了一个函数原型,名为m_pfnCreateObject,和通常的函数申明不同的是,它是一个函数指针。
    (PASCAL* xxx)()将这个指针首先结合到PASCAL栈调用协定上,接着通过括号结合成一个函数指针声明。
    最后,这个函数指针不带参数,并且返回一个CObject*类型的对象的指针。注意到MFC的类体系基本上以CObject为依托,这个函数的功用就出来了:函数被调用后返回一个CFormView,CDocument,CMainFrame一样的对象地指针。这个指针被简化到CObject类型,但是你可以通过对象多态性正确使用这个对象指针。你也可以通过第一例的机制动态识别对象的真实类型。你也可以通过类似于DYNAMIC_DOWNCAST()《好像是这样拼写的,jy注》这样的宏动态地强制那个返回指针到确切的类型上去。
      

  3.   

    多谢几位的指点,关于##的意义我是知道的,正如gohst001(唐怕猫)所说,
    变为static AFX_CLASSINIT _init_xxx(&xxx::classxxx);之后,
    那么这个_init_xxx(&xxx::classxxx)是什么意思,在何处实现,如何调用呢?
    还请指点.
      

  4.   

    一定要搞懂?其实不求甚解很好的。以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); }
    现在,你把它连通起来读一读吧、
      

  5.   

    抱歉:替换失误,最后一段应该是:好,预处理继续完成展开,上面的最后部分被展开为:
    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); }
      

  6.   

    这个RUNTIME_CLASS()有什么用处呢?这个class##class_name成员又有什么用处呢?
    看RUNTIME_CLASS(CDoc)展开后将会得到:
       ((CRuntimeClass*)(&CDoc::classCDoc))
       //((CRuntimeClass*)(&class_name::class##class_name))
    如何,这个纽带就这么连上了。一定要去钻研这个的话,就多动手自己去做展开,多了之后就明白了。
    宏替换带给你便利的时候,同时给自己留下了难读难维护的后果。所以需要权衡利弊的使用宏,新流派的C++提倡用inline函数来替代 宏替换 的功能,这是其中原因之一。
    (不过,对于上面的情况,AFX小组的确没有选择,除了这么一个方法之外,我想不出其他的解决方法,或许,只有模板了,但模板同样的麻烦)
      

  7.   

    JY,可能我还没说清楚,麻烦你再帮我解释一下:
    为什么使用AFX_CLASSINIT这个结构的构造函数就可以构造RTTI的链表,
    俄这个构造函数并没有显示执行,他与STATIC AFX_CLASSINIT _init_xxx()有什么关系?
    敬请指点迷津.
      

  8.   

    准确的说,这不是RTTI表。
    这是Afx的自行实现的动态对象识别。你还是应该查看MSDN的相关章节,例如IsKindOf()。注意到上面的"CDoc"串没有?这就是识别的依据。这是静态存储的变量(在classCDoc这个结构中),诸如IsKingOf(),STATIC_DOWNCAST()等等,基本上是在利用这个类名字的字符串进行工作。
    对于你说的_init_xxx,我想这是IMPLEMENT_SERIAL的一部分。这和对象的序列化存储有关。..
    (抱歉我要开会去了)