Ich habe vier Klassen (A
, B
, C
und) nach dem klassischen Diamantmuster und eine Container
Klasse mit einem unique_ptr<A>
. Ich möchte diese Klassen mithilfe der Serialisierungsbibliothek cereal serialisieren.Virtuelle Vererbung und Polymorphie: Verwirrt die Cerealienbibliothek das Objektlayout?
struct A {int f1; int f2; int f3}
struct B : public virtual A {
template<typename Archive>
inline void save(Archive& ar) const {
std::cerr << "Saving Obj: " << this << std::endl;
std::cerr << "This: " << &(this->f1) << " "
<< &(this->f2) << " " << &(this->f3) << std::endl;
std::cerr << "This: " << this->f1 << " "
<< this->f2 << " " << this->f3 << std::endl;
};
}
};
struct C : public virtual A {};
struct D : public B, public C {};
#include <cereal/archives/binary.hpp>
CEREAL_REGISTER_TYPE(B);
CEREAL_REGISTER_TYPE(C);
CEREAL_REGISTER_TYPE(D);
struct Container {
std::unique_ptr<A> obj;
template<typename Archive>
inline void save(Archive& ar) const {
std::cerr << "Saving Container" << std::endl;
std::cerr << "Obj Addr: " << obj.get() << std::endl;
std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2)
<< " " << &(pq->f3) << std::endl;
std::cerr << "Obj: " << " " << pq->sq_count << " " << pq->sq_bits
<< " " << pq->dim << std::endl;
ar(obj); // Call serialization for obj, ie B.save(...)
}
}
Alle Klassen haben Getreide save
und load
Funktionen, aber ich enthalten sie nur für B
und Container
, da sie die einzigen, die in diesem Beispiel verwendet werden.
Ich benutze diese Klassen wie folgt:
std::unique_ptr<A> obj(new B);
obj->f1 = 8;
obj->f2 = 8;
obj->f3 = 128;
std::unique_ptr<Container> db(new Container);
db.obj = std::move(obj);
std::ofstream out_file(out_filename);
cereal::BinaryOutputArchive out_archive(out_file);
out_archive(db);
Und ich bekomme die folgende Ausgabe:
Saving Container
Obj Addr: 0x23d2128
Obj: 0x23d2130 0x23d2134 0x23d2138 // Fields adresses (f1,f2,f3)
Obj: 8 8 128 // Fields values
Saving Obj: 0x23d2128 // Same object
This: 0x23d2118 0x23d211c 0x23d2120 // Different field adresses !
This: 4293296 0 37569440 // Garbage
Meine Frage ist: Ist es wahrscheinlich, dass dies einen Fehler in Getreide ist, oder gibt es etwas, das ich nicht mit virtueller Vererbung bekomme?
Wird erwartet, dass sich die Adressen der Felder eines bestimmten Objekts jemals in einem C++ - Programm ändern?
Warum sollte 'ar (obj)' 'B :: save (ar)' aufrufen? – aschepler
@aschepler Die Getreidebibliothek tut das: http://uscilab.github.io/cereal/serialization_functions.html – Xion345
Ich meine, 'obj' ist ein' std :: unique_ptr ', und die am meisten abgeleitete Art von' * obj' ist 'A'. Wo springt 'B' ein? – aschepler