COBJECT is most of the MFC class base classes to complete special functions such as MFC classes, dynamic generation, serialization, etc., add specific processing. In order to further enhance the understanding of the MFC class object, the COBJECT source code and related macro definition are analyzed. (The attached code is not the original code, which is deduced for the description of the problem.) Mainly introduced the following aspects: one .cobject brief statement
Class COBJECT
{
PUBLIC:
Virtual cruntimeclass * getruntimeclass () const;
Virtual ~ COBJECT ();
Void * Pascal Operator new (size_t nsize);
Void * Pascal Operator New (size_t, void * p);
Void Pascal Operator Delete (Void * P);
Void Pascal Operator Delete (Void * P, Void * PPLACE);
#if Defined // Debug mode, more nLINE parameters, used to save the original code line number.
Void * Pascal Operator New (size_t nsize, lpcstr lpszfilename, int nline);
Void Pascal Operator Delete (Void * P, LPCSTR LPSZFILENAME, INT NLINE);
#ENDIF
protected:
COBJECT ();
Private:
COBJECT (Const Cobject & Objectsrc);
Void Operator = (Const Cobject & ObjectSrc);
// attributes
PUBLIC:
Bool isserializable () const;
Bool iskindof (const cruntimeclass * pclass) const;
// Overridables
Virtual Void Serialize (CARCHIVE & A);
#if defined (_debug) // In debug mode
Virtual void assertvalid () const;
Virtual Void Dump (CDumpContext & DC) Const;
#ENDIF
PUBLIC:
Static const AFX_DATA CRUNTIMECLASS CLASSCOBJECT;
Static cruntimeclass * pascal _getbaseclass ();
}; Many of this statement are pure virtual functions, "interface" of a general object defined
Two .crunTimeClass structure
Include a static member variable in COBject
Static Cruntimeclass ClassCObject;
It is an important structure for the MFC to manage classes, which records important information from the class of many objects, which is managed by it at runtime. Many internal management member functions and macro definitions are based on CRUNTIMECLASS.
Struct cruntimeclass
{
// class name
LPCSTR M_LPSZCLASSNAME;
//size
INT m_nObjectsize;
//version
UINT M_WSCHEMA;
COBJECT * (Pascal * m_pfncreateObject) (); // null => Abstract Class
// Pointer to the base class CRUNTIMECLASS for inheritance relationships in the runtime record class.
#ifdef _AFXDLL
Cruntimeclass * (Pascal * m_pfNgetBaseClass) ();
#ELSE
Cruntimeclass * m_pbaseclass;
#ENDIF
// Operations
// Establish an object
COBJECT * CREATEOBJECT ();
// derived judgment
Bool isderiveDFrom (const cruntimeclass * pbaseclass) const;
// Implementation
//storage
Void Store (CARCHIVE & AR) Const;
//Read
Static CruntimeClass * Pascal Load (CARCHIVE & Ar, Uint * Pwschemanum);
// CruntimeClass Objects Linked TOGETHER in Simple List
Cruntimeclass * m_pnextclass; // linked list of registered classes
}
Three. Runtime_class
Runtime_class (class_name) is used to return a pointer to the runtime information structure, defined as follows:
#define runtime_class (Class_name) (CRUNTIMECLASS *) (& class_name :: class ## class_name))
Four. Dynamic support
In COBJECT derived class, you can get dynamic "verification" support, access runtime information
method:
Add Hong: Declare_Dynamic (class_name)
Adding a macro when implementing: import_dynamic
Original analysis:
Declare_Dynamic (class_name) is equivalent to adding as follows:
protected:
Static cruntimeclass * pascal _getbaseclass ();
PUBLIC:
// Static member CRUNTIMECLASS, add runtime information to this derived class,
// This allows you to use the CRUNTIMECLASS member to determine the information.
// This member name format is "Class" "class name", and the runtime_class () macro is a pointer to this structure.
Static const AFX_DATA CRUNTIMECLASS Class ## Class_name;
Virtual cruntimeclass * getruntimeclass () const; import_dynamic:
#define import_dynamic (class_name, base_class_name) /
Implement_runtimeclass (class_name, base_class_name, 0xfffff, null)
#define import_runtimeclass (class_name, base_class_name, wschema, pfnnew) /
/ / Return to the pointer to the base class runtime information structure
Cruntimeclass * pascal class_name :: _ getBaseClass () /
{RETURN Runtime_class (base_class_name);} /
// Initialize this class's runtime information, in turn, for class name, size, version, null, base class
AFX_COMDAT constimeclass class_name :: class ## Class_name = {/
#class_name, sizeof (class class_name), WSChema, PFNNEW, /
& class_name :: _ getBaseClass, Null}; /
// Return the runtime class information, overload the COBJECT GETRUNTIMECLASS, so that the interface declared in COBJECT is valid for the specific derived class
Cruntimeclass * class_name :: getRuntimeClass () const / {return runtime_class (class_name);} /
With this, you can use the runtime_class () macro, and use the Bool Iskindof (Const CRUntimeClass * PCLASS) Const judgment class type.
5. DyncReate support
Instances of class dynamics support
method:
Add declaration: Declare_Dyncreate (class_name)
Add Implementation: Implement_DyncReate (Class_name, Base_Class_Name)
Original analysis:
Declare_Dyncreate (class_name)
#define declare_dyncreate (Class_name) /
// Has Dynamic Support
DECLARE_DYNAMIC (Class_name) /
// Object establishment support
Static COBJECT * PASCAL CREATEOBJECT ();
Implement_dyncreate (class_name, base_class_name):
#define import_dyncreate (class_name, base_class_name) /
/ / Dynamically establish an object
COBJECT * PASCAL CLASS_NAME :: CreateObject () /
{RETURN New Class_name;} /
// Fill in the runtime information, different from Dynamic, there is a PFNNEW parameter
Implement_runtimeclass (class_name, base_class_name, 0xffff, /
Class_name :: CreateObject)
Six.Serial support
Store objects, and read established object support
method:
Add declaration: Declare_serial (class_name)
Add implementation: import_serial (class_name, base_class_name, wschema)
Original analysis
Declare_serial (class_name):
#define declare_serial (class_name) /
// Dynamic generation support
_Declare_dyncreate (class_name) /
// Document operator
AFX_API Friend Carchive & AFXAPI Operator >> (CARCHIVE & AR, CLASS_NAME * & PO);
Implement_serial (class_name, base_class_name, wschema):
#define import_serial (class_name, base_class_name, wschema) /
// Dynamic generation support
COBJECT * PASCAL CLASS_NAME :: CreateObject () /
{RETURN New Class_name;} /
/ / Fill in the runtime information, including the version number, generate function pointer
_IMPLEMENT_RUNTIMECLASS (Class_name, Base_class_name, Wschema, /
Class_name :: CreateObject) /
AFX_CLASSINIT _INIT _ ## Class_name (runtime_class (class_name)); /
// Document support implementation
CARCHIVE & AFXAPI Operator >> (CARCHIVE & AR, CLASS_NAME * & POB) /
{POB = (Class_name *) ar.readObject (runtime_class (class_name)); / return ar;} /
Rebate Virtual Void Serialize (CARCHIVE & AR) in the derived class; after reading the save and establishment of class data. Thereby implementing the preservation of the class, and reading dynamic establishment.