通过指向派生类的基指针来提升序列化

时间:2011-12-02 03:05:48

标签: c++ serialization boost

  

可能重复:
  Boost Serialization using polymorphic archives

我正在尝试使用指向派生类的基指针来序列化我的类,但这只是序列化了基类。

我刚读过http://www.boost.org/doc/libs/1_32_0/libs/serialization/doc/special.html#registration,但导出宏和寄存器功能似乎都没有改变。

考虑以下非常基本的类层次结构:

#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;
}

输出将是:

  

一个!

显然,我正在寻找的输出是A!乙!有什么办法可以实现吗?

编辑:好的,在查看评论中的相关条目之后,这是正在发生的事情。

有三件事需要改变:

  1. A类应该有一个虚函数,以便它被认为是多态的
  2. 需要导出派生类。 BOOST_CLASS_EXPORT(B)
  3. oa&lt;&lt; b而不是oa&lt;&lt; * B
  4. 它适用于标准的binary_oarchive,以及polymorphic_binary_oarchive。

    EDIT2:当我说b.cpp(.h)和main.cpp时,BOOST_CLASS_EXPORT会产生重复的符号:

    重复符号boost :: archive :: detail :: extra_detail :: init_guid :: g

1 个答案:

答案 0 :(得分:3)

我必须承认我不熟悉这个boost包,但是我复制并编译了代码,它产生的结果与提到的OP相同

意识到我们正在使用多态,我在public: virtual ~A(){};中添加了class A。此外,oa.register_type<B>();根据文档添加main,输出变为:

A!
B!

根据规范,只有polymorphic class时,班级才为declares or inherits a virtual function。对于非多态分类,也许多态不行。

编辑:

BOOST_CLASS_EXPORT(B);放在B.cpp而不是B.h似乎可以解决重新定义的问题。

编辑:

检查BOOST_CLASS_EXPORT(B)(重新格式化)的扩展结果:

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();
            }
        }
    }
}

对于标有NOTE的行:对于boost 1.42使用了匿名命名空间,如果将它放入多个cpp文件或放入头文件(使用g ++在ubuntu中测试)将没有问题,使用boost包与Ubuntu一起)。但是,在boost 1.48中,使用namespace extra_detail,这会在放入多个cpp文件时出现问题(在使用VS2010的Windows中测试,使用从主页下载的提升)。