Boost Serialization via base pointer to derived cl

2019-02-19 02:38发布

问题:

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

回答1:

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).