COBJECT class

xiaoxiao2021-03-06  14

COBJECT class

COBJECT is the root or base class of most MFC classes. There are many useful features: support for runtime information, support for dynamic creation, support for serialization, object diagnostics, and more. The MFC has born many classes from COBJECT, with one or more features of them. Programmers can also derive their own classes from the COBJECT class, using these features of the COBJECT class.

This chapter will discuss how MFC designs these features of the COBJECT class. First, check the definition of the COBJECT class, analyze its structure and method (member variables and member functions) support for COBJECT characteristics. Then, discuss the COBJECT characteristics and its implementation mechanisms.

COBJECT Structure The following is the definition of the COBJECT class: Class Cobject {public: // Dynamic Create Virtual CRUNTIMECLAS * GETRUNTIMECLASS () Const; Destructor Virtual ~ CObject (); // Virtual Destructors Are Necessary // and Construction Function-related memory allocation function, can be used for output diagnostic information VOID * PASCAL OPERATOR NEW (SIZE_T NSID); Void * Pascal Operator New (Size_T, Void * P); Void Pascal Operator Delete (VOID * P); #IF Defined (_Debug) &&! defined (_afx_no_debug_crt) Void * Pascal Operator New (Size_t Nsize, LPCSTR LPSZFILENAME, INT NLINE); #ENDIF / / By default, the replication constructor and assignment constructor are unavailable // if the program The author will pass the value or assignment to pass the object, will get a compilation error protected: // default constructor cobject (); private: // copy constructor, private cobject (const cobject & objectsrc); // no importtionation // assignment constructor private void operator = (const CObject & objectSrc); // no implementation // Attributes public: // associated with the runtime class information, serialization function BOOL IsSerializable () const; BOOL IsKindOf (const CRuntimeClass * pClass) Const; // Overridables Virtual Void Serialize (CARCHIVE & Ar); // Diagnostic Function Virtual Void AssertValid () Const; Virtual Void Dump (CDumpContext & DC) const; // Implementation public: // and dynamic Construction related to the object function static const AFX_DATA CRuntimeClass classCObject; #ifdef _AFXDLL static CRuntimeClass * PASCAL _GetBaseClass (); #endif}; can be seen from the above, CObject CRuntimeClass defines a static member variable of type: CRuntimeClass classCObject also defines groups Function: Constructor Conformatics Configuration Class, Diagnostics, Functions related to runtime information, and serialization related functions. Among them, a static function: _GetBaseClass; five virtual functions: destructor, getRuntimeclass, Serialize, AssertValid, Dump. These virtual functions should have more specific implementations in the COBJECT derived class. If necessary, the derived class may require them to call the realization of the base class first, such as serialize and dump require this. Static member variables ClassCObject and related functions have implemented support for COBJET features. The Characteristics of the COBJECT class, which are described separately and describe the methods of supporting these features in derived classes.

Support for runtime information

This feature is used to determine if an object belongs to a particular class (which is the instance of this class), or is derived from a particular class. COBJECT provides the iskindof function to implement this feature. The class derived from COBJECT has such a feature, which requires:

When you define this class, use the Declare_Dynamic (ClassNMAE) macro in the class description; use the import_dynamic (classname, baseclass) macro in the class's implementation file.

Support for dynamic creation

The concept of dynamic creation is mentioned earlier is the instance of the specified class when running. A large number of MFCs, as mentioned in the frame window objects, view objects, and document objects need to be created by the document template class (cdoctemplate) object.

The class derived from the COBJECT has a dynamically created function, which requires:

When you define this class, use the Declare_Dyncreate (ClassNMAE) macro in the class description; define a constructor without parameters (default constructor); use import_dyncreate (Classname, Baseclass) macro in the implementation file; Runtime_class gets the runtime information of the class and then creates an instance of such a class using the CRUNTIMECLASS member function CreateObject.

E.g:

Cruntimeclass * pruntimeclass = runtime_class (cnname)

// CNAME must have a default constructor

COBJECT * POBJECT = pruntimeclass-> CreateObject ();

// Detect whether it is an instance of a CNAME class with iskindof

Assert (POBJECT-> iskindof (runtime_class (cname));

Serialized support

"Serialization" is the process of depositing the object content into a file or reading object content from a file. The class derived from the COBject is serialized, and it is required:

When you define this class, use the Declare_Serial (ClassNMAE) macro in the class description; define a constructor without parameters (default constructor); use the Implement_Serial (ClassName, Baseclass) macro in the implementation file; override the Serialize member function. (If you call the serialize function directly to sequence and read and write, you can omit three steps.)

Support, dynamically created support, serialized support layers (excluding direct calling serailize implementation sequence), and sequentially. If supported behind the back, you must support the previous functional support. Support for dynamic creation, you must support runtime information; support serialization, it is necessary to support the previous two functions because their declarations and implementations are the latter contain the former.

Comprehensive example:

Define a class CPERSON that supports serialization:

Class CPERSON: Public COBJECT

{

PUBLIC:

Declare_serial (CPERSON)

/ / Default constructor

CPERSON () {} {};

CString M_Name;

Word m_number;

Void Serialize (CARCHIVE & Archive);

// rest of class decaration

}; Implement the member function serialize of this class, override the function of COBJECT:

Void CPERSON :: Serialize (CARCHIVE & Archive)

{

/ (Implementation of the base class function first

COBJECT :: Serialize (Archive);

// now do the stuff for u f c c c

Archive.Istoring ())

Archive << m_name << m_number;

Else

Archive >> m_name >> m_number;

}

Use runtime information:

CPERSON A;

ASSERT (a.iskindof));

ASSERT (a.iskindof (runtime_class (cobject)));

Dynamically created:

Cruntimeclass * pruntimeclass = runtime_class (cPerson)

// CPERSON has a default constructor

COBJECT * POBJECT = pruntimeclass-> CreateObject ();

Assert (POBJECT-> iskindof (runtime_class (cPerson));

The mechanism of implementing the COBJECT feature is clearly understood, and the structure of the COBJECT is also clearly used by the programmer to use the COBJECT characteristic of the COBJECT. Today, how these methods use the COBJET structure, how these methods are supported. First, we must reveal the contents of Declare_Dynamic and other macros, then analyze the role of these macros.

Declare_dynamic

The MFC provides two definitions for Declare_Dynamic, Declare_DyncReate, Declare_Serial declaration macros, separately linking to MFC DLL and dynamic links to MFC DLL. There are two definitions that correspond to macro IMPLEMNET_XXXX, but it is not enumerated here.

The definition of MFC on these macros is as follows:

#ifdef _afxdll // Dynamic Link to MFC DLL

#define declare_dynamic (class_name) /

protected: /

Static cruntimeclass * pascal _getbaseclass (); /

PUBLIC: /

Static const AFX_DATA CRUNTIMECLASS CLASS ## Class_name; /

Virtual cruntimeclass * getRuntimeClass () const; /

#define _Declare_dynamic (class_name) /

protected: /

Static cruntimeclass * pascal _getbaseclass (); /

PUBLIC: /

Static AFX_DATA CRUNTIMECLASS Class ## Class_name; /

Virtual cruntimeclass * getRuntimeClass () const; /

#ELSE

#define declare_dynamic (class_name) /

PUBLIC: /

Static const AFX_DATA CRUNTIMECLASS CLASS ## Class_name; /

Virtual cruntimeclass * getRuntimeClass () const; /

#define _Declare_dynamic (class_name) /

PUBLIC: /

Static AFX_DATA CRUNTIMECLASS Class ## Class_name; / Virtual CRUNTIMECLASS * GETRUNTIMECLASS () Const; /

#ENDIF

// Not Serializable, But Dynamically Constructable

#define declare_dyncreate (Class_name) /

DECLARE_DYNAMIC (Class_name) /

Static COBJECT * PASCAL CREATEOBJECT ();

#define declare_serial (class_name) /

_Declare_dyncreate (class_name) /

Friend Carchive & Afxapi Operator >> (CARCHIVE & AR, CLASS_NAME * & PO);

Since these declarations are used in the definition of COBECT derived class, it can be seen from the above definitions of these macros that the declare_dynamic macro adds a CRUNTIMECLASS type static data member class ## class_name (class name) Added Class, for example, if the class name is CPERSON, the variable name is classcPerson), and is specified as const; two (when using the MFC DLL, otherwise, one) member function: Virtual function getRuntimeClass and static functions _GetBaseClass MFC DLL).

The DECLARE_DYNCREATE macro contains Declare_Dynamic, on this basis, also defines a static member function CreateObject.

Declare_serial macro includes _Declare_dyncreate, and overloads the operator ">>" (Frieist function). It is different from the first two macros that CRUNTIMECLASS data member class ## class_name is not specified as const.

Correspondingly, the MFC uses three macros to initialize the static variable defined by the DECLARE macro and implements the function of the DECLARE macro: import_dynamic, import_dyncreate, import_serial.

First, these three macro initializes the static member variables of the cruntimeclass type Class # class_name. Implement_serial is different from the other two macros, and does not specify the variable as const. The initialization content is given when CruntimeClass is discussed next section.

Second, it implements the member function of the Declare macro statement:

_GetBaseClass ()

Returns the runtime information of the base class, that is, a static member variable of the cruntimeClass type of the base class. This is a static member function.

GetRuntimeClass ()

Returns your own run class information, that is, the static member variable of its CRUntimeClass type. This is a virtual member function.

For dynamically created macros, there is a static member function CreateObject, which creates a dynamic object of this class using the C operator and class default constructor.

Operator's overload

For serialized implementation macro IMPLEMENT_SERIAL, the operator << and define a static member variable

Static const AFX_CLASINIT _INIT _ ## class_name (runtime_class (class_name));

For example, for CPerson, this variable is _init_cperson, its purpose is to initialize the static member before the application starts, so that the constructor of the AFX_ClassInit class is called, so that the constructor of the AFX_CLASSINIT class is inserted in the module status. Constructor CruntimeClass class information indicated by the function parameter. As for the module state, there is a detailed discussion later. The overloaded operator function is used to read the content of the class object from the document when serialization is a friend. Defined as follows:

CARCHIVE & AFXAPI Operator >> (CARCHIVE & AR, CLASS_NAME * & PO)

{

POB = (Class_name *) ar.readObject (

Runtime_class (class_name));

Return AR;

}

Review the COBJECT definition, it also has a static member variable of the CRUntimeClass type ClassCObject because it also supports three features.

ISKINDOF and dynamic creation functions can play with COBJECT and its derived static member variables ClassCObject, iskindof and dynamic creation functions.

Why does this variable have such a use, which analyzes the structure and content of the cruntiMeclass type variable. Below, after the structure of the CruntimeClass is discussed, the content of the static variable of this type is expressed by different macros.

Structure and function of CRUntimeClass classes

As can be seen from the discussion above, the CRUntimeClass class has played a key role in the support of the COBJECT characteristics. Here, it examines its structure and function.

CRuntimeClass structure CruntimeClass following structure: Struct CRuntimeClass {LPCSTR m_lpszClassName; // name of the class int m_nObjectSize; UINT m_wSchema // size classes; CObject * (PASCAL * m_pfnCreateObject) (); // pointer to function, equal to newclass. CreateObject () // after IMPLEMENT CRuntimeClass * (PASCAL * m_pfnGetBaseClass) (); CRumtieClass * m_pBaseClass; // operator: CObject * CreateObject (); BOOL IsDerivedFrom (const CRuntimeClass * pBaseClass) const; ...} CRuntimeClass member variables in there Both are function pointers, and there are several names used to save the class of the CRUNTIMECLASS object, the size of the class (number of bytes), etc. These member variables are initialized by three implementations, such as: m_pfncreateObject, will be initialized to point to the static member function CreateObject of the class. The CREATEOBJECT function is defined by the macro when initialization, and see the description of the above. M_PFNGETBASECLASS, if _afxdll is defined, the variable will be initialized to point to the member function of the class. _GetBaseClass declares in the declaration macro, which is implemented by the macro when initialization, see the description of the above. Next, three macros are analyzed in the case where the COBJECT and the CRUNTIMECLASS type of the COBJECT, and then discusses the implementation of the CRUntimeClass member function. Member Variable Class ## Class_name's content import_dyncreate and other macros will initialize all domains of the CRUNTIMECLASS type static member variable, Table 3-1 lists the three different levels of dynamic information, dynamic creation, and serialization. Initialization of Member Variables: Table 3-1 Static member variable Class ## Class_name initialization

CRUNTIMECLASS Member Variable Dynamic Class Dynamic Creating Serialization M_LpszclassName Class Name String Class Class Name String Class Name String M_NObjectsize Size (byte) Class Size (byte) M_WShema 0xfffFFF class member functions _GetBaseClass CRuntimeClass variable m_pfnGetBaseClass class variables CRuntimeClass CRuntimeClass base class variables of the base class member function CreateObject m_pBaseClass base class member function CreateObject class 0xFFFF 1,2 and the like, non-0 m_pfnCreateObject NULL class class member functions _GetBaseClass Member function _getbaseclass m_pnextclass null null m_wschema type is UINT, defining the version of the program saved to the document in the serialization. If the serialization characteristics are not required, the domain is 0xfffff, otherwise, it cannot be 0. The COBJECT class itself static member variable classcobject is initialized to: {"cobject", sizeof (cobject), 0xfff, null, & cobject :: _ getBaseClass, null}; the initialization content is explained: Class name strings are "cobject", class The size is Sizeof (COBject), which is not required to support serialization, and is not supported. Member function CreateObject review Section 3.2, the object is dynamically created by the statement pRuntimeClass-> CreateObject completed, that is called CRuntimeClass own member functions, CreateObject function calls function m_pfnCreateObject pointed to dynamically create tasks to complete, as follows: CObject * CRuntimeClass :: createObject () {if (m_pfncreateObject == null) // Judgment function pointer is empty {trace (_t ("error: trying to create object which is not") _t ("declare_dyncreate / nor declare_serial:% HS. / N "), m_lpszClassName); return NULL;} // function pointer is not empty, processing continues CObject * pObject = NULL; TRY {pObject = (* m_pfnCreateObject) (); // create objects dynamically} END_TRY return pObject;} member functions IsDerivedFrom This function is used to help runtime to determine if a class is derived from another class, and is called by the COBJECT member function iskindof function. It is described as follows: If _AFXDLL is defined, the member function isderiveDFrom calls the functionality of the member function M_PFNGetBaseClass to get a static member variable of the cruntimeclass type of the base class by layer by layer until a static member variable of the cruntimeclass type of a base class and The CruntimeClass variable specified by the parameter is consistent or pursued to the uppermost layer. If you don't define _afxdll, use a static member variable of the CRUNTIMECLASS type of the member variable m_pbaseclass base class.

Procedure as follows: BOOL CRuntimeClass :: IsDerivedFrom (const CRuntimeClass * pBaseClass) const {ASSERT (! This = NULL); ASSERT (AfxIsValidAddress (this, sizeof (CRuntimeClass), FALSE)); ASSERT (! PBaseClass = NULL); ASSERT (AFXISVALIDDRESS (PBASECLASS, SIZEOF (CRUNTIMECLASS), FALSE)); // Simple Si Case const cruntimeclass * pclassthis = this; while (pclassthis! = Null) // From this class to the top-up base class search {ix (pclassthis == PBaseClass) // If the parameter specified class information return true; // class information does not match, continue to search for the base class #ifdef _afxdll pclassthis = (* pclassthis-> m_pfNgetBaseClass) (); #ELSE PCLASS = PCLASSTHIS-> m_pbaseclass; # Endif} return false; // Search, no match, return false. } Because the member variable of the CRUntimeClass type is a static member variable, if the two class CRUntimeClass member variables are the same class, it must be the same class. This is the foundation for ISDERIVEDFROM and ISKINDOF. Runtime_class macro runtime_class macro is confirmed as follows:

#define runtime_class (class_name) (& Class_name :: Class ## Class_name)

In order to easily get a static member variable of the CRUntimeClass type of each class (COBJECT or its partial category), the MFC defines this macro. It returns a reference to the CRUNTIMECLASS type member variable for class class_name, which is "class" plus class_name (name). E.g:

Runtime_class (cobject) gets references to ClassCObject;

Runtime_class (CPERSON) gets references to Class CPerson.

Dynamic information, dynamic creation principle

MFC's implementation principle for COBJECT dynamic class information, dynamic creation:

Dynamic class information, dynamic creation is based on the static member variable of the CRUNTIMECLASS type added to the class, summarizes the following.

C does not support dynamic creation, but supports the creation of dynamic objects. Dynamic creation is incomplete to create a dynamic object, because the instance of creating a class from a class name is ultimately a dynamic object that is created in this class. The key is that from a class name to get the code that creates its dynamic objects.

How can I get the code for this class to create a dynamic object before a class does not have any instances? This goal can be achieved by means of static member data technology for C :

Static member data is initialized before the entry of the program (Main or Winmain). Therefore, in a static member data, the type information is placed, dynamically create functions, etc., it is possible to get this member data. No matter how many instances created, the static member data has only one. All instances of all classes share a static member data, to determine if a class is an instance of a class, and only the static data is used to use this class.

From the previous two discussions, Declare_CREATE, etc., the macro defines a static member variable: type is CRUNTIMECLASS, naming conventions are "calss" plus class name; importime_create, etc., the runtime_class macro is used to get the member variable. The principle of dynamic class information has been explained when analyzing the member function ISDeriveDFROM of CRUNTIMECLASS.

Dynamically created the process and principle, with the figure, indicating that its process is as follows:

Note: The step-by-step indentation in one of the following boxes indicates a layer-by-layer call relationship.

Serialized mechanism

As described by the above, a class is to support implementation serialization, so that it can be saved to the document or can be read into memory from the document and generate an object, and requires dynamic class information, and needs to cover the base class. The serialize virtual function is serialized for its object.

It is not enough support, and the MFC also provides an archive class carchive to support the read and write of simple types of data and complex objects.

CARCHIVE acts as an agent between files and memory objects. It is responsible for writing memory objects to a file in a certain order and format, or read it, can be seen as a binary stream. It and the relationship between the file class CFILE is shown in Figure 3-2:

A CARCHIVE object has a mediation role between the sequenceful objects and storage media (Storage Medium, can be a file or a socket). It provides a series of methods to perform serialization, not only serialize int, float, etc., but also serialize complex data such as String, etc., more importantly, it can put complex objects (including composite Objects) Perform sequence. These methods are overloaded operators >> and <<. For simple types, it directly implements different read and write operations for different types; for complex objects, each of its support serialized classes have heavy loads >>, from the front section, you can clearly see this: Implement_Serial Operators >> are overloaded to the class. As for the << operation, you don't have to be overloaded every serialization class.

The "<<" operation of complex objects, first search for the CRUNTIMECLASS linked list of this module status to see if there is a "<<" The run class information specified by the "second parameter" (the search process involves the module status, will be at 9.5.2) Description) If there is (none, return), first use this information dynamic creation object (this is the reason for the serialization class must provide dynamic class information, support dynamically created), then call the server from the storage of the serilize function from the storage The media read into the object content.

The ">>" operation of the complex object first writes the run class information of the object class into the storage medium, and then call the server content to the storage medium for the object content to call the server content to the SERILIZE function.

When you create a CARCHIVE object, you must have a CFILE object that represents the storage medium. Typically, the programmer does not have to do this job, the MFC will automatically create the CFILE object and the CARCHIVE object and call the serialize function of the serialization class when appropriate. Such a process will be seen when discussing (5.3.3.2) or close (6.1) documentation.

When the CARCHIVE object is created, you need to specify whether it is used to read or use to write, ie the direction specifies the serialization operation. Serialize function Applicable CARCHIVE Function Isstoring Determination CARCHIVE is used to read data or write data.

转载请注明原文地址:https://www.9cbs.com/read-50108.html

New Post(0)