2014-05-27 4 views
1

Я реализовал структуру класса ниже. Я хотел бы сериализовать эти объекты.не может десериализоваться с boost :: serialization и shared_ptr

class Base 
{ 
public: 
    Base(void) = default; 

    virtual double func(void) const = 0; 


private: 
    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    {} 
}; 

class DerivedA : public Base 
{ 
public: 
    DerivedA(void) = default; 
    DerivedA(double a) 
    : a_(a) {} 

    virtual double func(void) const 
    { 
    return std::exp(a_); 
    } 

private: 
    double a_; 

    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
    ar & a_; 
    } 
}; 


class DerivedB : public Base 
{ 
public: 
    DerivedB(void) = default; 
    DerivedB(double b) 
    : b_(b) {} 

    virtual double func(void) const 
    { 
    return std::log(b_); 
    } 

private: 
    double b_; 

    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
    ar & b_; 
    } 
}; 

Я хочу создать вектор shared_ptr для этих объектов и сериализовать и десериализовать их. Сериализация выглядит нормально, но я не могу их десериализовать. Есть идеи?

void out(void) 
{ 
    std::vector<std::shared_ptr<Base>> objects; 
    std::shared_ptr<Base> m1(new DerivedA(1.0)); 
    std::shared_ptr<Base> m2(new DerivedB(4.0)); 
    objects.push_back(m1); 
    objects.push_back(m2); 

    std::ofstream ofs("filename"); 
    boost::archive::text_oarchive oa(ofs); 

    for(auto o : objects) 
    { 
    oa << *o; 
    } 
} 

void in(void) 
{ 
    std::ifstream ifs(filename); 
    boost::archive::text_iarchive ia(ifs); 

    std::vector<std::shared_ptr<Base>> objects; 

    std::shared_ptr<Base> m1(new DerivedA()); 
    ia >> *m1; 
    models.push_back(m1); 
    std::shared_ptr<Base> m2(new DerivedB()); 
    ia >> *m2; 
    models.push_back(m2); 
} 

Cheers, Майк

+0

Может быть, это просто опечатка, но я не вижу, где переменная «имя файла» объявлена ​​в вашем «в» функции. Если filename = "filename", ваш ifstream скорее всего будет читать неправильный файл. – user1074069

ответ

1

Вот мой взгляд на него: Live On Coliru

Примечание:

  • использование boost::shared_ptr

  • использование

    BOOST_SERIALIZATION_ASSUME_ABSTRACT(Base) 
    BOOST_CLASS_EXPORT_KEY(DerivedA) 
    BOOST_CLASS_EXPORT_KEY(DerivedB) 
    
  • использование

    ar & boost::serialization::base_object<Base>(*this); 
    

    установить полиморфную ссылку

  • использование

    ar.template register_type<DerivedA>(); 
    ar.template register_type<DerivedB>(); 
    
  • сериализации через указатель, а не (л) стоимость

#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/shared_ptr.hpp> 
#include <boost/serialization/export.hpp> 
#include <boost/make_shared.hpp> 
#include <fstream> 

class DerivedA; 
class DerivedB; 

class Base 
{ 
    public: 
     Base(void) = default; 
     virtual ~Base() = default; 

     virtual double func(void) const = 0; 

    private: 
     friend class boost::serialization::access; 
     template<class Archive> 
      void serialize(Archive & ar, const unsigned int version) 
      { 
       ar.template register_type<DerivedA>(); 
       ar.template register_type<DerivedB>(); 
      } 
}; 

typedef boost::shared_ptr<Base> BasePtr; 

class DerivedA : public Base 
{ 
    public: 
     DerivedA(void) = default; 
     DerivedA(double a) 
      : a_(a) {} 

     virtual double func(void) const 
     { 
      return std::exp(a_); 
     } 

    private: 
     double a_; 

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


class DerivedB : public Base 
{ 
    public: 
     DerivedB(void) = default; 
     DerivedB(double b) 
      : b_(b) {} 

     virtual double func(void) const 
     { 
      return std::log(b_); 
     } 

    private: 
     double b_; 

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

BOOST_SERIALIZATION_ASSUME_ABSTRACT(Base) 
BOOST_CLASS_EXPORT_KEY(DerivedA) 
BOOST_CLASS_EXPORT_KEY(DerivedB) 

void out(std::string filename) 
{ 
    std::vector<BasePtr> objects; 
    BasePtr m1(new DerivedA(1.0)); 
    BasePtr m2(new DerivedB(4.0)); 
    objects.push_back(m1); 
    objects.push_back(m2); 

    std::ofstream ofs(filename); 
    boost::archive::text_oarchive oa(ofs); 
    oa.template register_type<DerivedA>(); 
    oa.template register_type<DerivedB>(); 

    oa << objects; 
} 

std::vector<BasePtr > in(std::string filename) 
{ 
    std::ifstream ifs(filename); 
    boost::archive::text_iarchive ia(ifs); 
    ia.template register_type<DerivedA>(); 
    ia.template register_type<DerivedB>(); 

    std::vector<BasePtr> objects; 

    ia >> objects; 

    return objects; 
} 

int main() 
{ 
    out("test.out"); 
    auto r = in("test.out"); 
    return r.size(); 
} 
+0

Отлично! Большое спасибо, майк – Mike

+0

в качестве продолжения? в чем проблема с std :: shared_ptr? – Mike

+1

@ Майк, да, это не поддерживается :) Это должно быть довольно легко адаптировать (просто скопируйте/вставьте из 'serialization/shared_ptr.hpp', я думаю). – sehe

Смежные вопросы