【问题标题】:boost serialization of derived object doesn't call derived's serialize()派生对象的增强序列化不调用派生的序列化()
【发布时间】:2012-03-31 20:43:00
【问题描述】:

我已经阅读了大量类似的问题,但没有找到答案。我正在使用 Visual Studio 2010 和 boost 1.47。

这是代码,它是完整且可编译的:

#include "stdafx.h"

#include <string>
#include <sstream>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <boost/serialization/export.hpp>

using namespace std;

class BaseObject 
{
public:

    BaseObject(void) { };
    virtual ~BaseObject(void) { };

    template<class Archive>
      void serialize(Archive &ar, const unsigned int version)
      { /* nothing happens here */  };
};

class DerivedObject : public BaseObject
{
public:

    string text;

public:

    DerivedObject(void) { };
    ~DerivedObject(void) { };

    template<class Archive>
      void serialize(Archive &ar, const unsigned int version)
      {
          ar & text;
      };
};

BOOST_CLASS_EXPORT(DerivedObject)

int _tmain(int argc, _TCHAR* argv[])
{
    DerivedObject der;
    der.text = "Testing!";

    std::ostringstream os;
    boost::archive::text_oarchive oa(os);
    oa.register_type<DerivedObject>();

    // I made a DerivedObject, but I'm casting it to a BaseObject
    // as the serialization code should not have to know what type it is
    BaseObject *base = &der;
    // now serialize it
    oa << *base;

    printf("serialized: %s\r\n",os.str().c_str()); 

    return (0);
}

你可以看到它真的很简单,我添加了 BOOST_CLASS_EXPORT 和 oa.register_type 魔法,它们应该确保调用 DerivdObject::serialize(),即使它不是虚拟方法..但仍然只是序列化BaseObject 中的 () 被调用。可能是 Visual C++ 特有的问题?请指教?

【问题讨论】:

  • 你的BaseObject::serialize不应该被标记为virtual吗?
  • 好点 - 没有注意到模板位!

标签: c++ serialization boost export derived


【解决方案1】:

我没有在调试器或任何东西中尝试过这个,但看起来它可能是切片的情况。也许您可以通过修改代码以按指针或按引用而不是按值进行序列化来找出答案,就像这样...

BaseObject *base = &der;
oa << base;  // Serialize a pointer

...或...

BaseObject& base = der;
oa << base;  // Serialize a reference

【讨论】:

  • 谢谢,但是第一个抛出异常,未注册类的东西,另一个和我的代码基本相同。结果一样...
  • 后来我意识到&lt;&lt; 运算符可能无论如何都通过引用来获取参数,这使我的理论完全错误。对不起。您是否尝试过注册基类?我正在工作中的当前项目中使用这些东西,但所有细节都是由其他人设置的,所以我对设置部分并不完全清楚。 ://
【解决方案2】:

这不是一个严格的答案,只是一个笨拙的解决方法。

在基类中添加:

virtual void StreamToArchive(boost::archive::text_oarchive &oa) = 0;

然后定义一个宏 STREAMTOARCHIVE 并把它放到每一个派生类中。

#define STREAMTOARCHIVE void StreamToArchive(boost::archive::text_oarchive &oa) { oa << *this; }

然后在main中,替换

oa << base;

base.StreamToArchive(oa);

是的,我知道,它很丑陋,但是.. 它工作得很好,我只需要将 STREAMTOARCHIVE 宏放在派生类中......我可以忍受......

但是……再把它解析回一个对象,那就是另一回事了……

已编辑:将 'this' 更改为 '*this'

【讨论】:

    【解决方案3】:

    boost serialization documentation 中所述,您需要告诉派生类调用基类序列化代码。只需像这样编写派生类序列化方法:

      template<class Archive>
      void serialize(Archive &ar, const unsigned int version)
      {
          ar & boost::serialization::base_object<BaseObject>(*this);
          ar & text;
      };
    

    【讨论】:

      猜你喜欢
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-25
      • 2013-10-10
      • 1970-01-01
      • 2015-12-05
      相关资源
      最近更新 更多