DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏[通俗易懂]

DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏[通俗易懂]自定义一个CTView类,继承于CView类的子类CScrollView类,然后再自定义一个CRView类,继承于CTView类,发现在主窗口中调用CRView类的虚函数OnInitialUpdate()时,它就是不去执行CRView类的这个方法,后面发现是没有添加DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,因为是继承于自定义的View类,所以它不会自动添加DELC

大家好,欢迎来到IT知识分享网。

自定义一个CTView类,继承于CView类的子类CScrollView类,然后再自定义一个CRView类,继承于CTView类, 发现在主窗口中调用CRView类的虚函数OnInitialUpdate()时, 它就是不去执行CRView类的这个方法,后面发现是没有添加DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,因为是继承于自定义的View类,所以它不会自动添加DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC 这两个宏, 如果是直接继承于CView类或它的子类, 编译器则会自动添加这两个宏

—————————————————————————–

DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏详解

—————————————————————————–

MFC为了达到RTTI的功能实现使用了CRunTimeClass类,该类记录必要的信息,以便建立型录,用链表来实现,CRunTimeClass的成员变量类的名称,链表的First指针和Next指针。

      MFC为了把CRunTimeClass放进类中,就主要使用了DELCLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏。

 

#define RUNTIME_CLASS(class_name)(&class_name::class##class_name)其中class##class_name为类中

 

#define DECLARE_DYNAMIC(class_name) \

public: \

        static CRuntimeClass class##class_name; \

        virtual CRuntimeClass* GetRuntimeClass() const;

 

CRuntimeClass结构体变量,##告诉编译器把class和class_name连接起来。

 

DECLARE_DYNAMIC作用:声明类中的静态CRuntimeClass变量,使这个类中的所有对象共享。以前学习到静态变量但是不知为何用,现在在这里用到了。

 

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \//这就是IMPLEMENT_DYNAMIC完成的功能

        _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)

 

其中_IMPLEMENT_RUNTIMECLASEE也是一个宏。

#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \  此为换行符

        static char _lpsz##class_name[] = #class_name; \把类名格式化为字符串,这是静态的数据成员,类的所有对象共享

        CRuntimeClass class_name::class##class_name = { \

                _lpsz##class_name类名,以零结束的字符串,

                sizeof(class_name)//大小, wSchem//版本号a, pfnNew, \

                        RUNTIME_CLASS(base_class_name), NULL }; \

        static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name); \加入链表

        CRuntimeClass* class_name::GetRuntimeClass() const \

                { return &class_name::class##class_name; } \

其中AFX_CLASSINIT是一个结构体,它表示一个构造函数。

struct AFX_CLASSINIT

        { AFX_CLASSINIT(CRuntimeClass* pNewClass); };//声明

AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)//定义

{

        pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;

        CRuntimeClass::pFirstClass = pNewClass;

}

 

例子:在MFC中经常会用到这两个宏。

//在头文件

class CView : public CWnd

{

                DECLARE_DYNAMIC(CView) //在MFC中实际是显示                                                                   DECLARE_DYNCREATE

                 …

};

//在实现文件

IMPLEMENT_DYNAMIC(CView,CWnd) //在MFC中实际是显示                                                                IMPLEMENT_DYNCREATE

将两个宏展开就可以简单建构数据并完成加入链表的工作。

 

 

 

IMPLEMENT_DYNAMIC是实现“运行时类型识别”宏,与之相对应的是DECLARE_DYNAMIC(声明“运行时类型识别”宏)。也就是说你在.CPP文件中如果看见有IMPLEMENT_DYNAMIC,则在.H文件中必定有DECLARE_DYNAMIC的声明。
DECLARE_DYNAMIC/DEClARE_DYNAMIC是为了确定运行时对象属于哪一个类而定义的宏。
DEClARE_DYNCREATE/IMPLEMENT_DYNCREATE是为了“动态创建”类的实例而定义的宏。new可以用来创建对象,但不是动态的。比如说,你要在程序中实现根据拥护输入的类名来创建类的实例,下面的做法是通不过的:
char szClassName[60];
cin >> szClassName;
CObject* pOb=new szClassName; //通不过
这里就要用到DEClARE_DYNCREATE/IMPLEMENT_DYNCREATE定义的功能了。

定义:

//
// Helper macros for declaring CRuntimeClass compatible classes

#ifdef _AFXDLL
#define DECLARE_DYNAMIC(class_name) \
protected: \
    static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
    static const CRuntimeClass class##class_name; \
    static CRuntimeClass* PASCAL GetThisClass(); \
    virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \
protected: \
    static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
    static CRuntimeClass class##class_name; \
    static CRuntimeClass* PASCAL GetThisClass(); \
    virtual CRuntimeClass* GetRuntimeClass() const; \

#else
#define DECLARE_DYNAMIC(class_name) \
public: \
    static const CRuntimeClass class##class_name; \
    virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \
public: \
    static CRuntimeClass class##class_name; \
    virtual CRuntimeClass* GetRuntimeClass() const; \

#endif

引用:

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结构,注意,这不是一个宏
//为了看得更加清楚,我按照struct定义的惯常格式来写这个struct的定义
struct AFX_CLASSINIT {

    AFX_CLASSINIT(CRuntimeClass *pNewClass);
};

AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass *pNewClass)
{

    pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
    //让m_pNextClass指向pFirstClass所指的CRuntimeClass变量

    CRuntimeClass::pFirstClass = pNewClass;
    //让pFirstClass指向pNewClass所指的变量,也就是本class的CRuntimeClass静态变量
}

 注意这个错误:
Entity.obj : error LNK2001: unresolved external symbol “public: virtual struct CRuntimeClass * __thiscall CEntity::GetRuntimeClass(void)const ” (?GetRuntimeClass@CEntity@@UBEPAUCRuntimeClass@@XZ)
DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC   
DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE   
DECLARE_SERIAL/IMPLEMENT_SERIAL   
请保证DECLARC宏的参类是它所在类的类名,IMPLEMENT的参数是(类名,基类名)

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/26324.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信