In main.cpp:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
#include <iostream>
using namespace boost;
using namespace std;
class Actor
{
public:
Actor( void ) {}
Actor( char gender )
: gender( gender )
{}
virtual ~Actor() {}
char Gender( void ) const { return gender; }
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & gender;
}
char gender;
};
class Crit: public Actor
{
public:
Crit( void ) {}
Crit( int age )
: age( age )
{
}
int Age( void ) const { return age; }
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object< Actor >( *this );
ar & age;
}
int age;
};
BOOST_CLASS_EXPORT_GUID( Crit, "Crit")
class Food: public Actor
{
public:
Food( void ) {}
Food( int energy )
: energy( energy )
{
}
int Energy( void ) const { return energy; }
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object< Actor >( *this );
ar & energy;
}
int energy;
};
BOOST_CLASS_EXPORT_GUID( Food, "Food")
template< typename T >
void save( T& data, string filename )
{
ofstream ofs( filename.c_str() );
boost::archive::text_oarchive oa( ofs );
oa & data;
}
template< typename T >
void load( T& data, string filename )
{
ifstream ofs( filename.c_str() );
boost::archive::text_iarchive ia( ofs );
ia & data;
}
void TestAlpha( void )
{
shared_ptr< Crit > critAlpha( new Crit( 18 ) );
shared_ptr< Crit > critBravo( new Crit( 19 ) );
shared_ptr< Food > foodAlpha( new Food( 20 ) );
shared_ptr< Food > foodBravo( new Food( 21 ) );
vector< shared_ptr< Actor > > conAlpha;
vector< shared_ptr< Actor > > conBravo;
conAlpha.push_back( critAlpha );
conAlpha.push_back( foodAlpha );
// save
string filename = "sav.sav";
save( conAlpha, filename );
// test
assert( critBravo->Age() == 19 );
assert( foodBravo->Energy() == 21 );
// load
load( conBravo, filename );
// test
critBravo = dynamic_pointer_cast< Crit >( conBravo[ 0 ] );
assert( critBravo->Age() == 18 );
foodBravo = dynamic_pointer_cast< Food >( conBravo[ 1 ] );
assert( foodBravo->Energy() == 20 );
}
int main( int argc, const char* argv[] )
{
TestAlpha();
return EXIT_SUCCESS;
}
In Makefile (remember to put a real tab before where it says 'g++'):
all:
g++ -g -Wall testBoostSerializationInheritance.cpp -lboost_serialization
Error you may encounter 1:
/usr/include/boost/shared_ptr.hpp:209: error: cannot dynamic_cast ‘r->boost::shared_ptr::px’ (of type ‘class Actor* const’) to type ‘class Food*’ (source type is not polymorphic)
To fix this error, make sure that you have a virtual function in your base class. For example:
virtual ~Actor() {}
Error you may encounter 2:
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): unregistered class
To fix this error, make sure that you register your classes by doing for example the following:
BOOST_CLASS_EXPORT_GUID( Crit, "Crit")
Error you may encounter 3:
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): unregistered void cast
To fix this error, make sure that you put the following line in your derived class serialization method:
ar & boost::serialization::base_object<>( *this );
Hi Paul,
ReplyDeleteWhile doing same, i am getting below error message
cilpp0_cfg.cpp:36: error: expected initializer before ‘<’ token
cilpp0_cfg.cpp:36: error: ISO C++ forbids declaration of ‘type name’ with no type
cilpp0_cfg.cpp:36: error: wrong number of template arguments (1, should be 2)
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_pair.h:68: error: provided for ‘template class _T1, class _T2 struct std::pair’
can u suggest, what could be the cause of error ?
Hi cpgarg10,
ReplyDeleteI can't think of anything that might be the cause of the error. Can you show me some code around line 36?
Hi cpgarg10,
ReplyDeleteI reread your error message and noticed that your code requires two template arguments and at the moment your code only has one. You may need to give a bit more information. For example,
function< float, int >()
or
dataStructure< float, float > myDataStructure
I hope that helps.
Hi Binh Nugyen,
ReplyDeleteI am sorry for not following your replies. Actually problem is, you can't use macro BOOST_CLASS_EXPORT_GUID from any name space
For example:
namespace sample
{
BOOST_CLASS_EXPORT_GUID (XXX, "XXX");
}
My code for XML serialization was inside some namespace, so it was causing compilation error.
To fix this problem, first i have forward declared my class and then exported these macro from global name space.
Thanks for the wonderful article, it helped me a lot !!
Regards,
--cpgarg10
Hi cpgarg10!
ReplyDeleteI'm glad you found this post useful. Thanks for taking the time to write about what you found out. :)
Your post is already about 4 years old and yet helps me over and over solving my boost::serialization problems. Thank you!
ReplyDeleteHi Markus,
ReplyDeleteThat's awesome! Thanks for leaving a comment, much appreciated.