zoukankan      html  css  js  c++  java
  • DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏的详细解释

    DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏的详细解释
    最近有些朋友在看《深入浅出MFC》的时候,被第三章的几个宏给卡住了,记得我第一次看此书时,也被这几个宏给卡住。当然真正卡人的其实是第一个,也就是DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC。我做了一个详解,供同样被卡住的朋友做个参考:)

    说明:这两个宏的主要目的,是在所指定的class(比如CView)的声明和实现里,加上一些静态成员函数和静态成员变量。所以,不要管“”这个换行标志,就把里面的每一句话当作是在类里的声明或者是实现。另外,“##”和"#"符号我就不不赘述了。
    另外,建议结合《深入浅出MFC》这本书,JJHou写了一些展开宏的实例,结合实例看这个解释可能效果会比较好一点:)

    DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC

    #define DECLARE_DYNAMIC(class_name)    
    public:
        static CRuntimeClass class##class_name;
        //声明一个类型为CRuntimeClass的静态public成员变量,变量名是由字符串"class"
        //与所指定的类的类名组成。举例而言,如果你写DECLARE_DYNAMIC(CMyView),则等于声明了一个
        // static CRuntimeClass classCMyView静态变量

        virtual CRuntimeClass* GetRuntimeClass() const;
        //声明一个虚函数,函数名为GetRuntimeClass,返回值为CRuntimeClass类型的指针
        //无参数,并且是个const函数

    #define IMPLEMENT_DYNAMIC(class_name,bass_class_name)
           _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL)

    #define _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew)
        static char _lpsz##class_name[]= #class_name;
        //定义一个C类型字符串静态变量,变量名由"_lpsz"和指定类的类名组成,变量值为该指定类型的名字
        //比如是CMyView,那么定义的就是static char _lpszCMyView="CMyView";

        CRuntimeClass class_name::class##class_name = {
            _lpsz##class_name,sizeof(class_name),wSchema,pfnNew,
                RUNTIME_CLASS(base_class_name),NULL};
        //给之前在DECLARE_DYNAMIC里定义的CRuntimeClass类型的静态成员变量赋值
        //当然,除最后一个m_pNextClass没有赋值(赋值为NULL,它由下面的结构处理)

        static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name);
        //初始化一个名为"_init_##class_name"的AFX_CLASSINIT静态结构,主要作用是给指定的class_name的
        //class##class_name静态变量的最后一个成员m_pNextClass赋值,具体见下面解释AFX_CLASSINIT中

        CRuntimeClass* class_name::GetRuntimeClass

    () const
            { return &class_name::class##class_name;}
        //之前在DECLARE_DYNAMIC里定义的GetRuntimeClass的实现,很简单,就一个return语句。

    #define RUNTIME_CLASS(class_name)
            (&class_name::class##class_name)
    //这部分之所以单独define出一个宏,主要是为了方便从某个指定的class直接得到它的CRuntimeclass静态成员

    //以下是解释AFX_CLASSINIT结构,注意,这不是一个宏,请回本贴就可以看下面内容
    本帖隐藏的内容需要回复才可以浏览


    [ 本帖最后由 成为高手 于 2008-10-29 08:49 编辑 ]
    学mfc学到文档,视图和框架的时候,知道必须在这三个类的派生类的类声明 
    里加上DECLARE_DYNCREATE,然后在类声明外合适的地方加上IMPLEMENT_DYNCREA 
    TE,然后文档,视图和框架,还有文档模板就可以协调工作了。查看msdn,发现 
    类似的宏有这几对: 
    DECLARE_DYNAMIC 和 IMPLEMENT_DYNAMIC 
    DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 
    DECLARE_SERIAL 和 IMPLEMENT_SERIAL 

    虽然msdn里介绍了他们的作用,但对于它们为什么会起这样的作用心里却没 
    底,于是翻了翻mfc的源代码,喜欢钻牛角尖的人可以和我一起来钻一钻。 

    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) 
    由于篇幅的原因,宏的具体定义代码就不列出来了,感兴趣的可以去看文件 
    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的参数有关的。在下文我们把这个成员变 
    量统统记做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所引入的一样的四个

    当前时区 GMT+8, 现在时间是 2009-2-20 18:57

    清除 Cookies - 联系我们 - - Archiver - WAP - TOP - 界面风格

    Powered by Discuz! 6.1.0 © 2001-2008 Comsenz Inc.

    Processed in 0.737032 second(s), 11 queries.

  • 相关阅读:
    BZOJ 2212/BZOJ 3702
    BZOJ 4761 Cow Navigation
    BZOJ 3209 花神的数论题
    BZOJ 4760 Hoof, Paper, Scissors
    BZOJ 3620 似乎在梦中见过的样子
    BZOJ 3940 Censoring
    BZOJ 3942 Censoring
    BZOJ 3571 画框
    BZOJ 1937 最小生成树
    BZOJ 1058 报表统计
  • 原文地址:https://www.cnblogs.com/jack-jia-moonew/p/4238024.html
Copyright © 2011-2022 走看看