Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost Serialization via base pointer to derived class [duplicate]

Possible Duplicate:
Boost Serialization using polymorphic archives

I am trying to serialize my classes using a base pointer to a derived class, but that only serializes the base class.

I just read http://www.boost.org/doc/libs/1_32_0/libs/serialization/doc/special.html#registration, but both the export macro and the register function didn't seem to change anything.

Consider the following, very basic, class hierarchy:

#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

class A
{
private:
  friend class boost::serialization::access;
  template <typename Archive>
  void serialize(Archive& ar, const unsigned int version)
  { 
    std::cout << "A!\n";
  }
};

class B : public A
{
private:
  friend class boost::serialization::access;
  template <typename Archive>
  void serialize(Archive& ar, const unsigned int version)
  {
    ar & boost::serialization::base_object<A>(*this);
    std::cout << "B!\n";
  }
};

int main()
{
  std::ofstream of("mybin.bin");
  boost::archive::binary_oarchive oa(of);

  A* b = new B();
  oa << b;

  delete b;

  return 0;
}

Output will be:

A!

Clearly, the output I'm looking for is A! B!. Is there any way this can be achieved ?

EDIT: Ok, after looking at the related entry in the comments, here is what is going on.

There was 3 things to change:

  1. class A should have a virtual function so that it is considered polymorphic
  2. need to export derived classes. BOOST_CLASS_EXPORT(B)
  3. oa << b instead of oa << *b

It works with a standard binary_oarchive, as well as the polymorphic_binary_oarchive.

EDIT2: When I have let's say b.cpp(.h) and main.cpp, the BOOST_CLASS_EXPORT results in duplicate symbols:

duplicate symbol boost::archive::detail::extra_detail::init_guid::g

like image 323
vdsf Avatar asked May 28 '26 20:05

vdsf


1 Answers

I must admit I am not familiar with this boost package, but I copied and compiled the code, which produced the same result as the OP mentioned

Realizing that we are using polymorphism, I added a public: virtual ~A(){}; in class A. Also, oa.register_type<B>(); is added in main according to the document, and output became:

A!
B!

According to the specification, a class is a polymorphic class only when declares or inherits a virtual function. For non-polymorphic classed, maybe polymorphism just does not work.

EDIT:

Putting the BOOST_CLASS_EXPORT(B); in B.cpp instead of B.h seems to solve this problem of redefinition.

EDIT:

Checked the expansion result of BOOST_CLASS_EXPORT(B) (reformatted):

namespace boost {
    namespace serialization {
        template<> struct guid_defined<B> : boost::mpl::true_ {};
        template<> inline const char * guid<B>(){ return "B"; }
    }
}
namespace boost {
    namespace archive {
        namespace detail {
            namespace { // NOTE
                template<> struct init_guid< B > {
                    static guid_initializer< B > const & g;
                };
                guid_initializer< B > const & init_guid< B >::g = ::boost::serialization::singleton< guid_initializer< B > >::get_mutable_instance().export_guid();
            }
        }
    }
}

And for the line marked with NOTE: for boost 1.42 used an anonymous namespace is used, which will be no problem if it is put into multiple cpp files or put into a header file (tested in ubuntu with g++, using the boost package come along with Ubuntu). However, in boost 1.48, namespace extra_detail is used, which would cause problems when put into multiple cpp files (tested in windows with VS2010, using boost downloaded from homepage).

like image 193
fefe Avatar answered May 31 '26 11:05

fefe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!