2009-01-26 30 views
9

Estoy trabajando en una aplicación cliente-servidor que usa la biblioteca boost :: serialization para sus necesidades de serialización.Serialización Boost usando archivos polimórficos

Necesito serializar y deserializar objetos polimórficos que no parecen funcionar. La documentación dice que es compatible, pero ninguno de los ejemplos relacionados demuestra lo que intento hacer aquí. Entonces, no estoy muy seguro. Mi pregunta es ¿puede serializar/deserializar objetos polimórficos usando boost? Si es así, ¿qué estoy haciendo mal aquí?

Gracias!

código:

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; 
} 
+0

Por favor, vuelva a formatear el código. Debe aplicar sangría a todo para que aparezca como un gran bloque de código. –

+0

Aunque el fondo de esto es su aplicación de red, la pregunta o asunto en sí no tiene nada que ver con la creación de redes. ¿Tal vez la etiqueta "network-programming" está obsoleta? – sharkin

Respuesta

10

encontrado una resolución. Tenía que exportar la clase derivada con la declaración:

BOOST_CLASS_EXPORT(derived); 

Publicación de algo que funciona con algunas correcciones.

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; 
} 
+0

Acabas de cambiar del archivo polimórfico al archivo de plantilla tradicional. Funciona, pero con salvedades. Dumpbin/exports en tu exe para ver cuánto bloat te da en Windows. Es realmente impresionante. – kizzx2

3

A pocos comentarios ...

En primer lugar, se puede utilizar la misma operación para serializar y deserializar usando una versión de plantilla:

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

Además, en lugar de la macro, puede "configurar" el archivo para esperar que esos tipos se reconozcan como punteros:

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

register_type resuelve este problema también para mí, pero por mi vida no puedo entender por qué algunas partes de mi estructura de clases exigen register_type, y otras no –

Cuestiones relacionadas