2009-01-26 8 views
9

Je travaille sur une application client-serveur qui utilise la librairie boost :: serialization pour ses besoins de sérialisation.Boost Sérialisation utilisant des archives polymorphes

Je dois sérialiser et désérialiser les objets polymorphes qui ne semblent pas fonctionner. La documentation dit qu'elle est supportée mais aucun des exemples associés ne montre ce que j'essaie de faire ici. Donc, je ne suis pas très sûr. Ma question est peut sérialiser/désérialiser des objets polymorphes en utilisant boost? Si oui, qu'est-ce que je fais mal ici?

Merci!

code:

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

Veuillez reformater votre code. Vous devez tout mettre en retrait pour le faire apparaître comme un gros bloc de code. –

+0

Même si l'arrière-plan est votre application de réseau, la question ou le sujet en soi n'a rien à voir avec le réseautage. Peut-être que la balise "network-programming" est obsolète? – sharkin

Répondre

10

Trouvé une résolution. J'ai dû exporter la classe dérivée avec la déclaration:

BOOST_CLASS_EXPORT(derived); 

Publier quelque chose qui fonctionne avec quelques corrections.

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

Vous venez de passer de l'archive polymorphe à l'archive de modèles traditionnelle. Cela fonctionne, mais avec des mises en garde. Dumpbin/exporte sur vous exe pour voir combien de balles il vous donne sur Windows. C'est vraiment magnifique. Le type de registre – kizzx2

3

Juste quelques commentaires ...

D'abord, vous pouvez utiliser la même opération pour sérialiser et désérialiser en utilisant une version modélisée:

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

En outre, au lieu de la macro, vous peut "configurer" l'archive pour attendre les types reconnus comme pointeurs:

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

résout ce problème pour moi aussi, mais pour la vie de moi je ne peux pas comprendre pourquoi certaines parties de ma structure de classe exigent register_type, et d'autres ne –

Questions connexes