3

新:我可以从 access.hpp 中使用它吗?

template<class Archive, class T>
inline void serialize_adl(Archive &, T &, const unsigned int);

这表明我可以定义一个将对象作为参数的不同序列化。

因此,下面的代码更改会起作用吗?

我想我的问题是如何在接口类上添加一个序列化方法,它将调用派生子类的序列化方法。

class Interface {
public:
    virtual void aVirtual() = 0;
private:
    friend class boost::serialization::access;
    template<class Archive, class T>
    void serialize_adl(Archive & ar, T & object, const unsigned int version)
    {
       // Would this work?????
       ar & object;
    }
};

template<class T>
class Derived : Interface {
public:
   Derived(T in) : m_data(in) {}
   virtual void aVirtual() { // Do something }
private:
    T m_data;
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
       ar & m_data;
    }
};

我目前从我的编译器收到以下错误:

error C2039: 'serialize' : is not a member of 'Interface'

这是不寻常的,因为对象在智能指针内,所以它应该知道它是什么类型:

std::unique_ptr<Interface> object = std::unique_ptr<Interface>(new Derived<int>(5));

因此,当我尝试序列化时:

archive >> *object;

因此我得到了错误。

4

3 回答 3

4

这里有两个问题:

  1. 您正在序列化一个模板类。这不是问题,是的,您可以以侵入方式(成员serialize)或非侵入方式(serialize通过 ADL 的免费功能)来执行此操作。正如文档(序列化模板)所述,shared_ptr<T>序列化的实现是这里非侵入式变体的一个很好的例子:


  2. 您正在通过多态指针序列化基类/派生类。对于序列化部分,这没什么特别的(你可以register_type或者你应该可以base_object<Interface>(this)在派生的serialize函数中使用。

    然而,在反序列化方面,您需要预测通过多态指针序列化的可能具体实例类型的完整列表。BOOST_EXPORT_CLASS宏是实现这一目标的最简单方法。但是,您必须列出您希望支持的模板的具体实例:

    BOOST_CLASS_EXPORT(Derived<std::string>)
    BOOST_CLASS_EXPORT(Derived<double>)
    BOOST_CLASS_EXPORT(Derived<int>) // include all subtypes we can expect in an input archive
    

    或者

    BOOST_CLASS_EXPORT_GUID(Derived<std::string>, "4ef5a3ff-168a-4242-846b-4886f48424b5")
    BOOST_CLASS_EXPORT_GUID(Derived<double>,      "d0ed9de6-584f-476d-9898-8234bcb4efdb")
    BOOST_CLASS_EXPORT_GUID(Derived<int>,         "505538f0-2dd1-43bd-92a2-506ed9659bbe") // include all subtypes we can expect in an input archive
    

情况的复杂性——以及混乱——源于您通过多态指针序列化派生类模板这一事实。同时。但从概念上讲,两者都很容易解决。

有点无关,

  • 是的,您可以使用免费功能序列化,请参阅下面的第 3 个替代版本。不过,它对您的帮助很小,只需要m_data公开访问即可。
  • 不要使用serialize_adl,因为它是一个实现细节

以下是集成了所有内容的三个示例:

  1. Live On Coliru- 生的Interface*

  2. Live On Coliru- 与shared_ptr<Interface>

  3. Live On Coliru- 与非侵入式serialize功能相同

列出第一个样本

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>

class Interface {
    public:
        virtual void aVirtual() = 0;
        virtual ~Interface() {}
    private:
        friend class boost::serialization::access;
        template<class Archive> void serialize(Archive&, unsigned) { }
};

BOOST_SERIALIZATION_ASSUME_ABSTRACT(Interface)

template<class T>
class Derived : public Interface {
    public:
        Derived(T in = 0) : m_data(in) {}
        virtual void aVirtual() { /*Do something*/ }
        T const& getData() const { return m_data; }
    private:
        T m_data;
        friend class boost::serialization::access;
        template<class Archive>
            void serialize(Archive& ar, unsigned)
            {
                ar & boost::serialization::base_object<Interface>(*this);
                //// alternatively, if you don't want to make the abstract base serializable:
                // boost::serialization::void_cast_register<Derived, Interface>();

                ar & m_data;
            }
};

BOOST_CLASS_EXPORT(Derived<std::string>)
BOOST_CLASS_EXPORT(Derived<double>)
BOOST_CLASS_EXPORT(Derived<int>) // include all subtypes we can expect in an input archive

int main()
{
    std::stringstream ss;

    {
        boost::archive::text_oarchive oa(ss);

        Interface* o = new Derived<int>(42);
        oa << o;

        delete o;
    }

    std::cout << "Serialized: '" << ss.str() << "'\n";

    {
        boost::archive::text_iarchive ia(ss);

        Interface* o = nullptr;
        ia >> o;

        if (auto p = dynamic_cast<Derived<int>*>(o))
            std::cout << "Deserialized into Derived<int> with data: " << p->getData() << "\n";

        delete o;
    }
}

样本输出:

Serialized: '22 serialization::archive 11 0 1 1 12 Derived<int> 1 0
0 42
'
Deserialized into Derived<int> with data: 42
于 2014-12-25T22:06:38.777 回答
0

好吧,也许这可以帮助您,或者我可能是错的;但是在c++继承中,没有调用子类方法的机制,因为一个类可以有很多子类,而超类没有子类的引用,因为从子类到超类的多态函数而不是模式反转。因此,您可以从派生类开始调用超类的函数。

此致。

于 2013-08-07T15:43:15.160 回答
-1

您应该只序列化派生对象。使用 dynamic_cast 进行类型转换

 class Interface { 
     virtual void f() = 0; 
 }; 

 template<class T> class Derived : public Interface {
     T m_data; void f(){}; 
 }; 

 Interface* object = new Derived<Type>();

 Derived<Type>* objectSer = dynamic_cast<Derived<Type>*>(object); 

 //serialization 
 std::ofstream ofs("filename"); 
 boost::archive::text_oarchive oa(ofs); oa << *objectSer; 
于 2014-12-25T18:46:11.077 回答