C++boost serialization (serialization) Library tutorial __c++

Source: Internet
Author: User
Tags class definition serialization

A very simple situation.

Non-intrusive version

Serializable members

Derived classes

Pointer

Array

STL Container

Version of the class

Split the Serialize into Save/load

File

The output file (archive) is similar to the output data stream (stream). Data can be stored in the file (archive) through the << or & operator:

AR << data;

AR & data;

The input file (archive) is similar to the input data stream (stream). Data can be loaded from the file (archive) via the >> or & operator.

AR >> data;

AR & data;

For the original data type, when these operations are invoked, the data is simply "stored/loaded" to/from the file (archive). For class data types, the Serialize function of the class is invoked. For the above operation, each serialize function is used to "store/load" its data members. This processing takes the form of recursion until all the data contained in the class is "stored/loaded".

A very simple situation.

The Serialize function is typically used to store and load data members of a class.

This library contains a program called Demo.cpp that describes how to use this library. Below, we will introduce the simplest case of the library application from this demo excerpt code.

#include <fstream>

Include headers that implement a Archivein simple text format

#include <boost/archive/text_oarchive.hpp>

#include <boost/archive/text_iarchive.hpp>

/////////////////////////////////////////////////////////////

GPS coordinate

//

Illustrates serialization for a simpletype

//

Class Gps_position

{

Private

Friend class Boost::serialization::access;

When the class Archive corresponds into an output Archive, the

& operator is defined similar to <<. Likewise, when the class Archive

is a type of input archive the & operator is defined similar to>>.

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

AR & degrees;

Ar & minutes;

Ar & seconds;

}

int degrees;

int minutes;

float seconds;

Public

Gps_position () {};

gps_position (int d, int m, float s):

Degrees (d), minutes (m), seconds (s)

{}

};

int main () {

Create and open a character archive for output

Std::ofstream OFS ("filename");

Boost::archive::text_oarchive OA (OFS);

Create class instance

Constgps_position g (24.567f);

Write class instance to archive

OA << G;

Close Archive

Ofs.close ();

... some time later restore the class instance to it orginal state

Create and open an archive for input

Std::ifstream IFS ("filename", std::ios::binary);

Boost::archive::text_iarchive IA (IFS);

Read class State from archive

Gps_position NEWG;

IA >> NEWG;

Close Archive

Ifs.close ();

return 0;

}

For each class that is stored by serialization, a function must exist to implement "store" all its state data. For each class that is loaded by serialization, a function must exist to implement "mount" all its state data. In the example above, these functions are template member functions serialize.

Non-intrusive version

In the above example is the intrusive design. A class needs to be serialized by its instance to change it. This is difficult in some situations. An equivalent optional design is as follows:

#include <boost/archive/text_oarchive.hpp>

#include <boost/archive/text_iarchive.hpp>

Class Gps_position

{

Public

Intdegrees;

int minutes;

float seconds;

Gps_position () {};

gps_position (int d, int m, float s):

Degrees (d), minutes (m), seconds (s)

{}

};

Namespace Boost {

Namespace Serialization {

Template<class archive>

void Serialize (Archive & Ar,gps_position & G, const unsigned int version)

{

AR & g.degrees;

AR & g.minutes;

AR & g.seconds;

}

}//Namespace serialization

}//Namespace boost

The Serialize function generated in this case is not a member function of the Gps_position class. It's a similar thing.

Non-intrusive serialization is primarily applied to the serialization of classes without changing the class definition. To implement this possibility, the class must provide sufficient information to update the class state. In this example, we assume that the class has a public member. Class state can be serialized without changing the class itself, only if it provides enough information to store and load the class.

Serializable members

A serializable class that can have serializable members, such as:

Class Bus_stop

{

Friend class Boost::serialization::access;

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

Ar & latitude;

AR & longitude;

}

Gps_position latitude;

Gps_position longitude;

Protected

Bus_stop (const gps_position & lat_, const gps_position & long_):

Latitude (Lat_), Longitude (long_)

{}

Public

Bus_stop () {}

The item # in effective C + + by Scott Meyers.

Re non-virtual destructors in base classes.

Virtual ~bus_stop () {}

};

Here, the members of the class type are serialized, just as the original type is serialized.

Note that when the instance "store" of the class Bus_stop, its archive (archive) operator invokes the Serialize function of latitude and longitude. This will call the serialize defined in Gps_position in turn to be "stored". In this approach, the entire data structure is stored through the Bus_stop Archive (archive) operator, Bus_stop is its root entry.

Derived classes

A derived class should contain serialization of its base class.

#include <boost/serialization/base_object.hpp>

Class Bus_stop_corner:public Bus_stop

{

Friend class Boost::serialization::access;

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

Serialize base class information

AR & Boost::serialization::base_object<bus_stop> (*this);

AR & Street1;

AR & Street2;

}

Std::string Street1;

Std::string Street2;

Virtual std::string description () const

{

return Street1 + "and" + Street2;

}

Public

Bus_stop_corner () {}

Bus_stop_corner (const gps_position & lat_, const gps_position &long_,

Const std::string & s1_, const std::string & s2_

):

Bus_stop (Lat_, Long_), Street1 (s1_), Street2 (s2_)

{}

};

Note that you do not call the serialization function of its base class directly in a derived class. Doing so seems to work, and it actually bypasses the code that the trace instance uses to store to eliminate redundancy. It also bypasses code written to the version information of the class in the file. Therefore, always declare serialize as a private function. The Declaration friend Boost::serialization::access will run the serialized inventory to take private variables and functions.

 

Pointer

Suppose we define a bus route containing a group of bus stops. Assume:

We can have several types of bus stop (remember that Bus_stop is a base class).

A given bus_stop can show more than one route.

A bus route is convenient to describe with a set of pointers to Bus_stop.

Class Bus_route

{

Friendclass boost::serialization::access;

Bus_stop * STOPS[10];

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

int i;

for (i = 0; i < ++i)

AR & Stops[i];

}

Public

Bus_route () {}

};

Each member of the array stops is serialized. However, remember that each member is a pointer. -What the real meaning is. Serializing an entire object requires that the original data structure be reconstructed at another place and time. With pointers to accomplish these, the value of the stored pointer is not sufficient, and the object to which the pointer points must be stored. When the member is finally loaded, a new object is created, and the new pointer is loaded into the members of the class.

All of this is done automatically by the serialization library. The object that is associated with the pointer, and the above code completes storage and loading.

 

Array

In fact, the above scheme is more complicated. The serialization library detects that the serialized object is an array and produces the equivalent code above. So the above code can be written for a shorter period:

Class Bus_route

{

Friend class Boost::serialization::access;

Bus_stop * STOPS[10];

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

AR & stops;

}

Public

Bus_route () {}

};

STL Container

The example above uses an array member. More such an application uses STL containers for such purposes. The serialization library contains code that is serialized for all STL containers. Therefore, the seed scheme works as we expect.

#include <boost/serialization/list.hpp>

Class Bus_route

{

Friend class Boost::serialization::access;

Std::list<bus_stop *> stops;

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

AR & stops;

}

Public

Bus_route () {}

};

Version of the class

Suppose we are satisfied with the Bus_route class and use it in the product. After a period of time, found that the Bus_route class needs to include the name of the line driver. So the new version is as follows:

#include <boost/serialization/list.hpp>

#include <boost/serialization/string.hpp>

Class Bus_route

{

Friend class Boost::serialization::access;

Std::list<bus_stop *> stops;

Std::string driver_name;

Template<class archive>

void Serialize (Archive & AR, const unsigned int version)

{

AR & driver_name;

AR & stops;

}

Public

Bus_route () {}

};

All right, finish. Abnormal... Occurs when the data file generated by the previous version is read. How to consider versioning issues.

Typically, the serialization library stores the version number in the archive for each serialized class. The default value is 0. When the file is loaded, the stored version number can be read out. The above code can be modified as follows:

#include <boost/serialization/list.hpp>

#include <boost/serialization/string.hpp>

#include <boost/serialization/version.hpp>

Class Bus_route

{

Friend class Boost::serialization::access;

Std::list<bus_stop *> stops;

Std::string driver_name;

Template<class archive>

Voidserialize (Archive & AR, const unsigned int version)

{

Only save/load driver_name for newer archives

if (Version > 0)

AR & driver_name;

AR & stops;

}

Public

Bus_route () {}

};

Boost_class_version (Bus_route, 1)

There is no need to maintain a version file for each class through the version of the application. A file version is a union of the versions of all the classes it consists of. The system allows files created by programs and previous versions to be backward compatible.

Split the Serialize into Save/load

The Serialize function is simple, concise, and ensures that class members are stored/loaded in the same order (the key of the serialized system). But there are cases where loading and storage are inconsistent, as is the case here. For example, a class with multiple versions occurs. The above scenario can be rewritten as:

#include <boost/serialization/list.hpp>

#include <boost/serialization/string.hpp>

#include <boost/serialization/version.hpp>

#include <boost/serialization/split_member.hpp>

Class Bus_route

{

Friend class Boost::serialization::access;

Std::list<bus_stop *> stops;

Std::string driver_name;

Template<classarchive>

void Save (Archive & AR, const unsigned int version) const

{

Note, version are always the latest when saving

AR & driver_name;

AR & stops;

}

Template<class archive>

void Load (Archive & AR, const unsigned int version)

{

if (Version > 0)

AR & driver_name;

AR & stops;

}

Boost_serialization_split_member ()

Public

Bus_route () {}

};

Boost_class_version (Bus_route, 1)

The Boost_serialization_split_member () macro generates code that invokes save or load, depending on whether the file is used for "storage" or "mount."

File

Our discussion here will focus on the serialization capabilities of the class. The actual encoding of the serialized data is implemented in the file (archive) class. The serialized data stream is the product of the serialization of the selected archive (archive) class. The key design determines the independence of these two components. Allow any serialization specification to be available for any file (archive).
 

In this guide, we used a file class-the text_oarchive for storage and the Text_iarchive class for loading. The interfaces of other file classes in the library are exactly the same. Once the serialization of the class has been defined, the class can be serialized to any file type.

If the current file set does not provide an attribute, format, or behavior requires a special application. Either create a new one or derive it from the existing ones. will be described in the subsequent document.
 

Note that our example save and load program data is in a program, which is for easy discussion. Usually, the loaded file may not be in the same program.

T complete Demo program-Demo.cpp includes:

Create various categories of stops, routes and schedules

Show it

Serialized into a file called "testfile.txt."

Restore to another structure

Display the stored structure

The output of this program confirms that all requirements for the serialization system are embodied in this system. The contents of an archive file that is ASCII text for a serialized file can be displayed.

Related Article

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.