[Echempp-devel] Clarifications about boost::serialization
Status: Beta
Brought to you by:
berndspeiser
|
From: Dominik B. <dom...@gm...> - 2007-04-08 08:38:55
|
Hello,
yesterday it was correctly pointed out by Bernd Speiser,
that serialization of whole class hierarchies necessitates
the usage of the Factory design pattern.
But it is not necessary to wrap up boost::serialization
with this kind of mechanism as it is already provided by
the library.
To illustrate the serialization capabilities consider the
example program below. One important point are the
BOOST_EXPORT_GUID makros which equip each
class with a globally unique identifier. If these are
omitted the code will compile, but when reading back
the objects at runtime an exception of type "unregistered class"
will be thrown. Otherwise the objects are correctly read
back without knowing the exact type (polymorphic base*).
Dominik Brugger
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>
#include <fstream>
#include <iostream>
class base
{
public:
base() : data(3.14) {}
virtual void print()
{
std::cout << "base.data " << data << std::endl;
}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int file_version)
{
ar & BOOST_SERIALIZATION_NVP(data);
}
double data;
};
class derived1 : public base
{
public:
derived1() : derived1_data(42) {}
virtual void print()
{
base::print();
std::cout << "derived1.data " << derived1_data << std::endl;
}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int file_version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base)
& BOOST_SERIALIZATION_NVP(derived1_data);
}
int derived1_data;
};
class derived2 : public base
{
public:
derived2() : derived2_data(123) {}
virtual void print()
{
base::print();
std::cout << "derived2.data " << derived2_data << std::endl;
}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int file_version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base)
& BOOST_SERIALIZATION_NVP(derived2_data);
}
int derived2_data;
};
BOOST_CLASS_EXPORT_GUID(base, "base");
BOOST_CLASS_EXPORT_GUID(derived1, "derived1");
BOOST_CLASS_EXPORT_GUID(derived2, "derived2");
void save(const char *testfile)
{
std::ofstream os(testfile);
boost::archive::xml_oarchive oa(os);
base *b1 = new derived1();
base *b2 = new derived2();
oa << BOOST_SERIALIZATION_NVP(b1);
oa << BOOST_SERIALIZATION_NVP(b2);
delete b1;
delete b2;
}
void load(const char *testfile)
{
std::ifstream is(testfile);
boost::archive::xml_iarchive ia(is);
// Note that we do not know anything about the type
// of stored objects at this point
base *b1 = NULL;
base *b2 = NULL;
// The factory design pattern is already included in
// boost::serialization
ia >> BOOST_SERIALIZATION_NVP(b1);
ia >> BOOST_SERIALIZATION_NVP(b2);
// Dump to stdout to check that we read back the right
// types
std::cout << "Read: ";
b1->print();
std::cout << "Read: ";
b2->print();
delete b1;
delete b2;
}
int main(int argc, char* argv[])
{
// Note that calls to save/load can be made in
// different program runs, compilation units etc.
save("test.xml");
load("test.xml");
return EXIT_SUCCESS;
}
|