DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)

Source: Internet
Author: User

I read some of the macro implementations of MFC very early, RUNTIME_CLASS, DECLARE_DYNAMIC, DECLARE_DYNCREATE, IMPLEMENT_DYNCREATE, etc. I am tired of reading them.

 

 Code Implementation

(Note: The following macros and their implementations are taken from 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)
(Note: RenderView is a class inherited from CFormView in MFC)


Equals:


Public:

Static const AFX_DATA CRuntimeClass classRenderView;

Virtual CRuntimeClass * GetRuntimeClass () const;


That is, declare a static CRuntimeClass variable and a virtual function GetRuntimeClass ()


About CRuntimeClass, its 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

};


Struct, with 6 members:

M_lpszClassName Class Name

M_nObjectSize object size

M_wSchema schema

M_pfnCreateObject function pointer (Object creation method)

M_pBaseClass/m_pfnGetBaseClass refers to the pointer to the Base Class Object/gets the pointer to the base class object function (the key to Runtime)

M_pNextClass points to the next class Object

  • 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 ();


That is, declare a static CRuntimeClass variable, a virtual function GetRuntimeClass (), and a static function CreateObject ()


About CObject, its 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

};


Include: GetRuntimeClass () method, static variable CRuntimeClass classCObject, static method _ GetBaseClass () (NULL, because no Base), IsKindOf () method, etc.

  • RUNTIME_CLASS

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


E. g.

RUNTIME_CLASS (RenderView)


Equals:

(CRuntimeClass *) (& RenderView: classRenderView ))

Converts the classRenderView static variable to the (CRuntimeClass *) pointer.

  • 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, 0 xFFFF, RenderView: CreateObject)


Equals:

AFX_COMDAT const AFX_DATADEF CRuntimeClass RenderView: classRenderView = {

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

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


CRuntimeClass * RenderView: GetRuntimeClass () const

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

(## Is the connection text, # RenderView is the RenderView string)


The implement includes the static classRenderView variable and the GetRuntimeClass () virtual function.

  • 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, 0 xFFFF ,"

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), 0 xFFFF, RenderView: CreateObject,

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


CRuntimeClass * RenderView: GetRuntimeClass () const

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

The implement includes the static classRenderView variable and the GetRuntimeClass () virtual function and the CreateObject () function.

Purpose

In summary, the purpose of this macro is to nest a CRuntimeClass object in the target object (such as RenderView) to support query conversion similar to the Runtime type (to support RTTI of MFC ?).


What is the purpose of supporting this? One use is DYNAMIC_DOWNCAST, that is, the object pointer implemented in MFC is converted from top to bottom at the class level:
E. g.
...
PCFormView * pView =...
PRenderView * pRenderView = DYNAMIC_DOWNCAST (RenderView, pView)
...

The implementation is as follows:

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; // encoded ed to the top, no match

}

Implementation principle: RenderView inherits from CFormView, and the latter inherits from CObject. They are nested with static CRuntimeClass objects, so you can query a pointer to the CFormView object (pCFormView) is it actually a pointer to the RenderView object by comparing the CRuntimeClass object (or its BaseRuntimeClass (or BaseRuntimeClass of BaseRuntimeClass ...) object) is notYes (compare pointer value)Is the static CRuntimeClass object (IsDerivedFrom method) contained in the RenderView class so simple?

If the object is the same (that is, the pointer value is equal), the conversion is successful. Otherwise, the conversion fails.


(Key: the embedded CRuntimeClass is static and can be accessed through classes and called through non-static functions of objects. This is the key to implementation. because each class inherited from the CObject level has a unique CRuntimeClass object corresponding to it, it can become an identifier of the type. If the identifier is the same, the types are certainly the same, and this identifier can be accessed both through classes and through objects at runtime, so it is named CRuntimeClass .)

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.