2009-01-26 4 views
9

Ich arbeite an einer Client-Server-Anwendung, die Boost :: Serialisierungsbibliothek für seine Serialisierungsanforderungen verwendet.Boost Serialisierung mit polymorphen Archiven

Ich muss polymorphe Objekte serialisieren und deserialisieren, die nicht zu funktionieren scheint. Die Dokumentation besagt, dass es unterstützt wird, aber keines der verwandten Beispiele zeigt, was ich hier versuche. Also bin ich mir nicht sicher. Meine Frage ist, kann polymorphe Objekte mit boost serialisieren/deserialisieren? Wenn ja, was mache ich hier falsch?

Danke!

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

Bitte formatieren Sie Ihren Code neu. Sie müssen alles einrücken, damit es als ein großer Codeblock angezeigt wird. –

+0

Obwohl der Hintergrund dafür Ihre Netzwerk-App ist, hat die Frage oder das Thema an sich nichts mit Networking zu tun. Vielleicht ist das "Netzwerkprogrammierung" -Tag veraltet? – sharkin

Antwort

10

eine Auflösung gefunden. Ich musste die abgeleitete Klasse mit der Anweisung exportieren:

BOOST_CLASS_EXPORT(derived); 

Posting etwas, das mit einigen Korrekturen funktioniert.

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

Sie haben gerade vom polymorphen Archiv zum traditionellen Vorlagenarchiv gewechselt. Es funktioniert, aber mit Vorbehalten. Dumpbin/Exporte auf Sie exe, um zu sehen, wie viel aufgebläht es Ihnen unter Windows gibt. Es ist wirklich atemberaubend. – kizzx2

3

Nur ein paar Kommentare ...

Erstens können Sie die gleiche Operation verwenden, um zu serialisiert und deserialisiert eine Templat-Version mit:

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

Auch anstelle des Makros, Sie kann das Archiv "konfigurieren", um diese als Zeiger erkannten Typen zu erwarten:

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

register_type löst dieses Problem auch für mich, aber für das Leben von mir kann ich nicht herausfinden, warum einige Teile meiner Klassenstruktur register_type und andere nicht verlangen –