[VC] detailed technical explanation of the declare_serial/implement_serial macro

Source: Internet
Author: User

Declare_dynamic indicates that the type information is supported. With this macro, we can determine what type A class is, such
Class;
Class B: Public;
A;
B;
Now there is a pointer class * pa that points to an object. How do you know whether PA points to object a or object B? If there is type information, we can know what object PA is. In fact, its internal implementation principle is a string. Therefore, when making this judgment, it is actually a string comparison.

Declare_dyncreate indicates dynamic creation. This is a bit similar to the com class factory.
In fact, it uses the cruntime class to record the address of the class's static function creation. This feature needs to be used in many places. The declare_serial mentioned below is a classic example.
Dynamic Creation is mainly used in "I Don't Know What class the object to be created is, but I know it must be derived from a base class ".

declare_serial refers to the serialization feature. It is a fully automated storage mechanism that stores an array of objects (which may contain objects of the, B, and C classes, it seems very easy to load data according to the storage conditions. However, we must consider one problem, this is how to write the Program so that the corresponding A, B, and C objects can be correctly created during loading. (Note, here are three different classes ). in addition, when writing this mechanism, the MFC designers did not know what classes would appear, and maybe d classes would appear. what should we do?
certainly, the storage mechanism must have Code that can determine the class type. therefore, the serialization mechanism declare_serial contains declare_dynamic, so that class names can be stored in files when they are stored.
OK. Now we can know what class we want to load when loading, but how can we create it? So declare_serial also contains declare_dyncreate, which is used to create objects.
so what are the special features of declare_serial? First, it must implement operator> (for specific reasons, let's take a look at the simple introduction and version control. In this way, we can be flexible in processing serialization.

First, remember that declare_serial is mainly used for smart storage, so we don't need this smart feature.
If we do not have declare_serial and void cmessg: serialize (carchive & AR), we can only store
Cdocument: serialize (AR)
{
If (AR. isstoring ())
{
// Store an object
Pmessg-> serialize (AR );
}
Else
{
// You must specify a new cmessg object;
Pmessg = new cmessg;
Pmessg-> serialize (AR );
}
}
In the above example, there is no serialization mechanism designed for us by Using MFC.

Let's look at the following example.

cdocument: serialize (AR)
{< br> If (AR. isstoring ()
{< br> // store an object
ar }< br> else
{< br> // you must specify a new cmessg object.
assert (pmessg = NULL );
ar> pmessg;
}< BR >}

It's amazing. How does ar determine the class to be created based on the file (emphasize that it depends on the file, not hard encoding.
It involves the following steps:
1. Because declare_serial overload the> operator, you can ensure that the> function of the cmessg class is called.
2.> the function actually calls the AR readobject (cruntimeclass *) function.
3. readobject first reads the class judgment information from the file (which may be a string or a class index) and obtains the class-corresponding classname;
4. The runtimeclass list is available in the module status of the program. Therefore, find the runtimeclass supported by the corresponding program (compared with classname) and obtain the corresponding runtimeclass;
5. runtimeclass contains the Createobject Method for object creation. Call this method to create the corresponding object. here, because Createobject is actually a new object, similar to new cmessg; in order to support serialization, there must be no parameter constructor.
6. After creating an object, call seralize (AR) to read the real object information.
7. Return the object pointer.
8. pmessg points to a corresponding object.

 

Simulation of six key MFC technologies
Declare_serial/Implement_serial macro
 

To load the <and> operations into multiple sub-databases, you must also put the serialize function into the category declaration without knowing it.
The best practice is to use macros.
Category: it can perform file read/write operations on the premise that it has the ability to dynamically generate. Therefore, MFC has designed two macros.
Declare_serialAnd implement_serial:

# DefineDeclare_serial(Class_name )/
Declare_dyncreate (class_name )/
Friend carchive & afxapi operator> (carchive & AR, class_name * & POB );
# Define implement_serial (class_name, base_class_name, wschema )/
Cobject * Pascal class_name: Createobject ()/
{Return New class_name ;}/
_ Implement_runtimeclass (class_name, base_class_name, wschema ,/
Class_name: Createobject )/
Carchive & afxapi operator> (carchive & AR, class_name * & POB )/
{POB = (class_name *) Ar. readobject (runtime_class (class_name ));/
Return Ar ;}/

In order to be able to process trivial tasks before each object is processed (read or write), such as determining whether or not the first time
When version numbers and file names are recorded, cruntimeclass requires two functions: load and store.

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
Cruntimeclass * m_pbaseclass;
Cobject * Createobject ();
Void store (carchive & AR) const;
Static cruntimeclass * Pascal load (carchive & AR, uint * pwschemanum );
// Cruntimeclass objects linked together in simple list
Static cruntimeclass * pfirstclass; // start of class list
Cruntimeclass * m_pnextclass; // Linked List of Registered classes
};

You have read the load function in the previous section. to simplify it, I removed its parameter and changed it to get it on the screen.
In fact, it should read a category name from the file. For the store function
The name is written to the file:

// Runtime class serialization code
Cruntimeclass * Pascal cruntimeclass: load (carchive & AR, uint * pwschemanum)
{
Word nlen;
Char szclassname [64];
Cruntimeclass * Pclass;
Ar> (word &) (* pwschemanum)> nlen;
If (nlen> = sizeof (szclassname) | ar. Read (szclassname, nlen )! = Nlen)
Return NULL;
Szclassname [nlen] = ~ /0 ~;
For (Pclass = pfirstclass; Pclass! = NULL; Pclass = Pclass-> m_pnextclass)
{
If (lstrcmp (szclassname, Pclass-> m_lpszclassname) = 0)
Return Pclass;
}
Return NULL; // not found
}
Void cruntimeclass: store (carchive & AR) const
// Stores a runtime class description
{
Word nlen = (Word) lstrlena (m_lpszclassname );
Ar <(Word) m_wschema <nlen;
Ar. Write (m_lpszclassname, nlen * sizeof (char ));
}
Class cscribdoc: Public cdocument
{
Declare_dyncreate (cscribdoc)
...
};
Class cstroke: Public cobject
{
Declare_serial (Cstroke)
Public:

Void serialize (carchive &);
...
};
Class crectangle: Public cobject
{
Declare_serial(Crectangle)
Public:
Void serialize (carchive &);
...
};
Class ccircle: Public cobject
{
Declare_serial(Ccircle)
Public:
Void serialize (carchive &);
...
};

In the. cpp file, perform the following actions:

Implement_dyncreate (cscribdoc, cdocument)
Implement_serial (cstroke, cobject, 2)
Implement_serial (crectangle, cobject, 1)
Implement_serial (ccircle, cobject, 1)

What then? Design the serialize functions of cstroke, crectangle, and ccircle.
Of course, it is not surprising thatSource codeCoblist and cdwordarray have the following content:

// In header files
Class cdwordarray: Public cobject
{
Declare_serial(Cdwordarray)
Public:
Void serialize (carchive &);
...
};
Class coblist: Public cobject
{
Declare_serial(Coblist)
Public:
Void serialize (carchive &);
...
};
// In implementation files

Implement_serial (coblist, cobject, 0)
Implement_serial (cdwordarray, cobject, 0)

Cobject also has a virtual function serialize:
Class cobject
{
Public:
Virtual void serialize (carchive & AR );
...
}

 

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.