declare dyncreate_declare搭配

declare dyncreate_declare搭配来自http://hi.baidu.com/zhaquanmin/item/830fe6a48e8891d95bf19183DECLARE_DYNAMIC宏的含义  DECLARE_DYNAMIC(class_name)  说明:  但从CObject派生一个类时,此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文件

declare dyncreate_declare搭配

来自http://hi.baidu.com/zhaquanmin/item/830fe6a48e8891d95bf19183

DECLARE_DYNAMIC 宏的含义

  DECLARE_DYNAMIC(class_name) 

  说明: 

   但从CObject派生一个类时,此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文件中,然后在全部需要访 问词类对象的.CPP文件中都包含此模块。如果像所描述那样使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用户便可使 用RUNTIME_CLASS宏和CObject::IsKindOf函数以在运行时间决定对象类。如果DECLARE_DYNAMIC包含在类定义中, 那么IMPLEMETN_DYNAMIC必须包含在类工具中。

       DECLARE_DYNCREATE 宏的含义

  DECLARE_DYNCREATE(class_name) 

  说明: 

   使用DECLARE_DYNCRETE宏以便允许CObject派生类的对象在运行时刻自动建立。主机使用此功能自动建立新对象,例如,但它在串行化过 程中从磁盘读一个对象时,文件及视图和框架窗应该支持动态建立,因为框架需要自动建立它。把DECLARE_DYNCREATE宏加入类的.H文件中,然 后在全部需要访问此类对象的.CPP文件中包含这一模式。如果DECLARE_DYNCREATE包含在类定义中,那么 IMPLEMENT_DYNCREATE必须包含在类工具中。

代码实现

(注:以下宏及其实现取自MFC)

  • DECLARE_DYNAMIC

Define:


#define DECLARE_DYNAMIC(class_name) “


public: “


    static const AFX_DATA CRuntimeClass class##class_name; “


    virtual CRuntimeClass* GetRuntimeClass() const; “




E.g.


DECLARE_DYNAMIC(RenderView)


(注:RenderView是继承于MFC中CFormView的一个类)




Equals:




public: 


    static const AFX_DATA CRuntimeClass classRenderView;


    virtual CRuntimeClass* GetRuntimeClass() const;




即declare了一个static的CRuntimeClass变量和一个虚拟函数GetRuntimeClass()




关于CRuntimeClass,其declaration:




struct CRuntimeClass


{



// Attributes


    LPCSTR m_lpszClassName;


    int m_nObjectSize;


    UINT m_wSchema; // schema number of the loaded class


    CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class


#ifdef _AFXDLL


    CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();


#else


    CRuntimeClass* m_pBaseClass;


#endif




// Operations


    CObject* CreateObject();


    BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;




// Implementation


    void Store(CArchive& ar) const;


    static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);




    // CRuntimeClass objects linked together in simple list


    CRuntimeClass* m_pNextClass;       // linked list of registered classes


};




结构体,6个成员:


m_lpszClassName 类名字


m_nObjectSize 对象大小


m_wSchema schema


m_pfnCreateObject 函数指针 (对象创建方法)


m_pBaseClass/m_pfnGetBaseClass 指向基类对象的指针/获取基类对象函数的指针 (Runtime的关键)


m_pNextClass 指向下一个此类对象

  • DECLARE_DYNCREATE

Define:


// not serializable, but dynamically constructable


#define DECLARE_DYNCREATE(class_name) “


    DECLARE_DYNAMIC(class_name) “


    static CObject* PASCAL CreateObject();






E.g.


DECLARE_DYNCREATE(RenderView)




Equals:




public: 


    static const AFX_DATA CRuntimeClass classRenderView;


    virtual CRuntimeClass* GetRuntimeClass() const;


    static CObject* PASCAL CreateObject();




即declare了一个static的CRuntimeClass变量和一个虚拟函数GetRuntimeClass()和一个static的函数CreateObject()




关于CObject,其declaration:




#ifdef _AFXDLL


class CObject


#else


class AFX_NOVTABLE CObject


#endif


{



public:




// Object model (types, destruction, allocation)


    virtual CRuntimeClass* GetRuntimeClass() const;


    virtual ~CObject(); // virtual destructors are necessary




    // Diagnostic allocations


    void* PASCAL operator new(size_t nSize);


    void* PASCAL operator new(size_t, void* p);


    void PASCAL operator delete(void* p);


#if _MSC_VER >= 1200


    void PASCAL operator delete(void* p, void* pPlace);


#endif




#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)


    // for file name/line number tracking using DEBUG_NEW


    void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);


#if _MSC_VER >= 1200


    void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine);


#endif


#endif




    // Disable the copy constructor and assignment by default so you will get


    //   compiler errors instead of unexpected behaviour if you pass objects


    //   by value or assign objects.


protected:


    CObject();


private:


    CObject(const CObject& objectSrc);              // no implementation


    void operator=(const CObject& objectSrc);       // no implementation




// Attributes


public:


    BOOL IsSerializable() const;


    BOOL IsKindOf(const CRuntimeClass* pClass) const;




// Overridables


    virtual void Serialize(CArchive& ar);




#if defined(_DEBUG) || defined(_AFXDLL)


    // Diagnostic Support


    virtual void AssertValid() const;


    virtual void Dump(CDumpContext& dc) const;


#endif




// Implementation


public:


    static const AFX_DATA CRuntimeClass classCObject;


#ifdef _AFXDLL


    static CRuntimeClass* PASCAL _GetBaseClass();


#endif


};




包含:GetRuntimeClass()方法,static变量 CRuntimeClass classCObject,static方法 _GetBaseClass() (为NULL,因为没有Base),IsKindOf()方法等.

  • RUNTIME_CLASS

#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))




E.g.


RUNTIME_CLASS(RenderView)




Equals:


((CRuntimeClass*)(&RenderView::classRenderView))


即将classRenderView static变量转换成((CRuntimeClass*)指针



  • IMPLEMENT_RUNTIMECLASS

Define:


#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) “


    AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { “


        #class_name, sizeof(class class_name), wSchema, pfnNew, “


            RUNTIME_CLASS(base_class_name), NULL }; “


    CRuntimeClass* class_name::GetRuntimeClass() const “


        { return RUNTIME_CLASS(class_name); } “




E.g.


IMPLEMENT_RUNTIMECLASS(RenderView, CFormView, 0xFFFF, RenderView::CreateObject)




Equals:


AFX_COMDAT const AFX_DATADEF CRuntimeClass RenderView::classRenderView = { 


        #RenderView, sizeof(class RenderView), 0xFFFF, RenderView::CreateObject, 


            ((CRuntimeClass*)(&CFormView::classCFormView)), NULL }; 




    CRuntimeClass* RenderView::GetRuntimeClass() const 


        { return ((CRuntimeClass*)(&RenderView::classRenderView)); } 






(##为连接文本, #RenderView为取RenderView字符串)




即implement了static classRenderView变量和GetRuntimeClass()虚拟函数

  • IMPLEMENT_DYNCREATE

Define:




#define IMPLEMENT_DYNCREATE(class_name, base_class_name) “


    CObject* PASCAL class_name::CreateObject() “


        { return new class_name; } “


    IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, “


        class_name::CreateObject)




E.g.


IMPLEMENT_DYNCREATE(RenderView, CFormView)




Equals:




    CObject* PASCAL RenderView::CreateObject() 


        { return new RenderView; } 




    AFX_COMDAT const AFX_DATADEF CRuntimeClass RenderView::classRenderView = { 


        #RenderView, sizeof(class RenderView), 0xFFFF, RenderView::CreateObject, 


            ((CRuntimeClass*)(&CFormView::classCFormView)), NULL }; 




    CRuntimeClass* RenderView::GetRuntimeClass() const 


        { return ((CRuntimeClass*)(&RenderView::classRenderView)); } 



即implement了static classRenderView变量和GetRuntimeClass()虚拟函数和CreateObject()函数.

用途

综合来看,这套宏的目的是在目标对象(比如RenderView)里面嵌套了一个CRuntimeClass对象,用来支持类似Runtime类型的查询转换等(用以支持MFC的RTTI?).




支持这些,有什么用呢?一个用处是DYNAMIC_DOWNCAST,即MFC里实现的对象指针在类层次上的从上到下转换:


E.g.





pCFormView* pView = …


pRenderView* pRenderView = DYNAMIC_DOWNCAST(RenderView, pView)







其实现如下:


CObject* AFX_CDECL AfxDynamicDownCast(CRuntimeClass* pClass, CObject* pObject)


{



    if (pObject != NULL && pObject->IsKindOf(pClass))


        return pObject;


    else


        return NULL;


}




BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const


{



    ASSERT(this != NULL);


    // it better be in valid memory, at least for CObject size


    ASSERT(AfxIsValidAddress(this, sizeof(CObject)));




    // simple SI case


    CRuntimeClass* pClassThis = GetRuntimeClass();


    return pClassThis->IsDerivedFrom(pClass);


}




BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const


{



    ASSERT(this != NULL);


    ASSERT(AfxIsValidAddress(this, sizeof(CRuntimeClass), FALSE));


    ASSERT(pBaseClass != NULL);


    ASSERT(AfxIsValidAddress(pBaseClass, sizeof(CRuntimeClass), FALSE));




    // simple SI case


    const CRuntimeClass* pClassThis = this;


    while (pClassThis != NULL)


    {



        if (pClassThis == pBaseClass)


            return TRUE;


#ifdef _AFXDLL


        pClassThis = (*pClassThis->m_pfnGetBaseClass)();


#else


        pClassThis = pClassThis->m_pBaseClass;


#endif


    }


    return FALSE;       // walked to the top, no match


}




实现原理:RenderView继承自CFormView,后者又继承自CObject,它们本身又嵌套了static CRuntimeClass对象,那么查询一个指向CFormView对象的指针(pCFormView)是不是实际上就是一个指向RenderView对象的指针的功能是通过比较pCFormView指向的对象中的CRuntimeClass对象(或者其BaseRuntimeClass(或BaseRuntimeClass的BaseRuntimeClass…)对象)是不是
就是(比较指针值)
RenderView类所含的static CRuntimeClass对象(IsDerivedFrom方法)这么简单了?




如果对象一样(即指针值相等)的话则可以转换成功,否则失败.




(关键:嵌入的CRuntimeClass是静态的,可以通过类访问,又可以通过对象的非静态函数调用,这是实现的关键.因为继承于CObject层次上的每个类都有唯一的CRuntimeClass对象与之对应, 所以它可以成为类型的一个标识符,如果表示符一样了,那么肯定类型是一样的,而这个标识符既可以通过类访问又可以在运行时刻通过对象访问,所以取名CRuntimeClass.)今天的文章declare dyncreate_declare搭配分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/58186.html

(0)
编程小号编程小号

相关推荐

发表回复

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