Повысить сериализацию с использованием полиморфных архивов - PullRequest
9 голосов
/ 26 января 2009

Я работаю над клиент-серверным приложением, которое использует библиотеку boost :: serialization для нужд сериализации.

Мне нужно сериализовать и десериализовать полиморфные объекты, которые, похоже, не работают. Документация говорит, что она поддерживается, но ни один из связанных примеров не демонстрирует, что я пытаюсь сделать здесь. Итак, я не очень уверен. Мой вопрос: можно ли сериализовать / десериализовать полиморфные объекты с помощью boost? Если да, что я здесь делаю не так?

Спасибо!

код:

using namespace std;  

class base {  
  public:
    int data1;  

    friend class boost::serialization::access;  

    void serialize(boost::archive::polymorphic_iarchive & ar, 
                   const unsigned int file_version) {  
        ar & data1;  
    }  

    void serialize(boost::archive::polymorphic_oarchive & ar, 
                   const unsigned int file_version){  
        ar & data1;  
    }  

  public:  
    base() {};  
    base(int _d) : data1(_d) {}  
    virtual void foo() const {std::cout << "base" << std::endl;}  
};  

class derived : public base {  
  public:  
    int data2;  

    friend class boost::serialization::access;  

    void serialize(boost::archive::polymorphic_iarchive & ar, 
                   const unsigned int file_version) {  
        ar & boost::serialization::base_object<base>(*this) & data2;  
    }  

    void serialize(boost::archive::polymorphic_oarchive & ar, 
                   const unsigned int file_version){  
        ar & boost::serialization::base_object<base>(*this) & data2;  
    }  

  public:  
    derived() {};  
    derived(int _b, int _d) : base(_b), data2(_d) {}  
    virtual void foo() const {std::cout << "derived" << std::endl;}  
};  

int main(int argc, char *argv[]) {  
    // client  
    const base *b1 = new derived(1, 2);  

    std::ostringstream oss;  
    boost::archive::polymorphic_text_oarchive oa(oss);  
    oa << *b1;  

    // server  
    base *b2 = new derived(3, 4);  

    std::istringstream iss(oss.str());  
    boost::archive::polymorphic_text_iarchive ia(iss);  
    ia >> *b2;  

    // prints 1, ok  
    cout << b2->data1 << endl;  

    // prints 4, why wasn't the derived class data written?
    cout << (dynamic_cast<derived*>(b2))->data2 << endl;  

    return 0;  
}  

Ответы [ 2 ]

10 голосов
/ 26 января 2009

Нашел разрешение. Мне пришлось экспортировать производный класс с заявлением:

BOOST_CLASS_EXPORT(derived);

Публикация чего-то, что работает с некоторыми исправлениями.

using namespace std;  

class base {  
  public:  
    int data1;  

    friend class boost::serialization::access;  

    template<typename Archive>  
    void serialize(Archive & ar, const unsigned int file_version) {  
        ar & data1;  
    }  

  public:  
    base() {};  
    base(int _d) : data1(_d) {}  
    virtual void foo() const {std::cout << "base" << std::endl;}  
};  

class derived : public base {  
  public:  
    int data2;  

    friend class boost::serialization::access;  

    template<typename Archive>  
    void serialize(Archive & ar, const unsigned int file_version) {  
        ar & boost::serialization::base_object<base>(*this);  
        ar & data2;  
    }  

  public:  
    derived() {};  
    derived(int _b, int _d) : base(_b), data2(_d) {}  
    virtual void foo() const {std::cout << "derived" << std::endl;}  
};  

BOOST_CLASS_EXPORT(derived);  

int main(int argc, char *argv[]) {  
    // client  
    // Assign to base type  
    std::unique_ptr<const base> b1(new derived(1, 2));  

    std::ostringstream oss;  
    boost::archive::text_oarchive oa(oss);  
    oa & b1.get();   

    // server  
    // Retrieve derived type from base  
    std::unique_ptr<base> b2;

    std::istringstream iss(oss.str());
    boost::archive::text_iarchive ia(iss);
    {
        base *temp; 
        ia & temp;
        b2.reset(temp);
    }
    cout << b2->data1 << endl;  
    cout << (dynamic_cast<derived*>(b2.get()))->data2 << endl;  

    return 0;  
}  
3 голосов
/ 04 февраля 2009

Всего несколько комментариев ...

Во-первых, вы можете использовать ту же операцию для сериализации и десериализации с использованием шаблонной версии:

template<class Archive>
void load(Archive & ar, const unsigned int version)
{
   ...
}

Кроме того, вместо макроса вы можете «настроить» архив на ожидание тех типов, которые распознаются как указатели:

ar.register_type(static_cast<your_static_type_here *>(NULL));
...