problem deserializing to base class pointer
I have a strange problem. I searched through the list and modified my initial code quite a bit but cannot seem to get this to work. Serialization seems fine, but deserialization to base pointer in particular doesn't seem to work correctly (I am getting instance of base class inside). The example below is canonical version of a much more complex case I was working with, involving shared_ptr and template classes, but it boiled down (for now) to this: A.h ---------------------------------------------------- #pragma once #include "boost/serialization/serialization.hpp" #include "boost/shared_ptr.hpp" class A { public: int t; A():t(0){}; //friend std::ostream& operator<<(std::ostream& os, const A& a); virtual ~A(){ }; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & t; } }; std::ostream& operator<<(std::ostream& os, const A& a) { return os << "A: t = " << a.t << std::endl; } typedef boost::shared_ptr<A> APtr; ---------------------------------------------------- B.h ---------------------------------------------------- #pragma once #include "boost/serialization/serialization.hpp" #include "boost/shared_ptr.hpp" class B: public A { public: int m; B():A(),m(0){}; ~B(){}; //friend std::ostream& operator<<(std::ostream& os, const B& b); friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object<A>(*this); ar & m; } }; std::ostream& operator<<(std::ostream& os, const B& b) { return os << "B: t = "<< b.t << "; m = "<< b.m << std::endl; } typedef boost::shared_ptr<B> BPtr; ---------------------------------------------------------------- Test.cpp ---------------------------------------------------------------- #include "stdafx.h" #include "boost/shared_ptr.hpp" #include "boost/serialization/shared_ptr.hpp" #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp> #include <istream> #include <ostream> #include <fstream> #include "A.h" #include "B.h" BOOST_CLASS_EXPORT(A) BOOST_CLASS_EXPORT(B) boost::archive::text_iarchive* GetiArchiveAndRegister(std::ifstream& f) { boost::archive::text_iarchive* ar= new boost::archive::text_iarchive(f); // ar->register_type(static_cast<A *>(NULL)); // ar->register_type(static_cast<B *>(NULL)); return ar; } boost::archive::text_oarchive* GetoArchiveAndRegister(std::ofstream& f) { boost::archive::text_oarchive* ar=new boost::archive::text_oarchive(f); // ar->register_type(static_cast<A*>(NULL)); // ar->register_type(static_cast<B*>(NULL)); return ar; } int _tmain(int argc, _TCHAR* argv[]) { A* a=new A(); a->t=1; B* b=new B(); b->t=2; b->m=1; A* c=new B(); c->t=2; std::ofstream f1("c:\\a"); boost::archive::text_oarchive* oa1=GetoArchiveAndRegister(f1); *oa1 & a; f1.close(); std::ofstream f2("c:\\b"); boost::archive::text_oarchive* oa2=GetoArchiveAndRegister(f2); *oa2 & b; f2.close(); std::ofstream f3("c:\\c"); boost::archive::text_oarchive* oa3=GetoArchiveAndRegister(f3); *oa3 & c; f3.close(); //deserializes fine std::ifstream f4("c:\\a"); boost::archive::text_iarchive* oa4=GetiArchiveAndRegister(f4); *oa4 & a; f4.close(); //deserializes an instance of A std::ifstream f5("c:\\b"); boost::archive::text_iarchive* oa5=GetiArchiveAndRegister(f5); *oa5 & a; f5.close(); //deserializes fine std::ifstream f6("c:\\c"); boost::archive::text_iarchive* oa6=GetiArchiveAndRegister(f6); *oa6 & a; f6.close(); //deserializes fine std::ifstream f7("c:\\b"); boost::archive::text_iarchive* oa7=GetiArchiveAndRegister(f7); *oa7 & b; f7.close(); std::ifstream f8("c:\\c"); boost::archive::text_iarchive* oa8=GetiArchiveAndRegister(f8); //runtime error: vector subscript out of range on the next line *oa8 & b; f8.close(); return 0; } ------------------------------------------------------------------ deserializations of f5 and f8 are controversial. I tried exchanging BOOST_CLASS_EXPORT calls with register_type call (commented out in GetiArchiveAndRegister and GetoArchiveAndRegister), and when that is done both serialization and deserialization finish correctly. I tried changing the order of includes, moving BOOST_CLASS_EXPORT around, etc. This version is what I'm settled for as the correct one. What am I doing wrong? Can anybody help?
Shipa wrote:
I have a strange problem.
I searched through the list and modified my initial code quite a bit but cannot seem to get this to work. Serialization seems fine, but deserialization to base pointer in particular doesn't seem to work correctly (I am getting instance of base class inside).
The example below is canonical version of a much more complex case I was working with, involving shared_ptr and template classes, but it boiled down (for now) to this:
...
std::ofstream f2("c:\\b"); boost::archive::text_oarchive* oa2=GetoArchiveAndRegister(f2); *oa2 & b; f2.close(); ... //deserializes an instance of A std::ifstream f5("c:\\b"); boost::archive::text_iarchive* oa5=GetiArchiveAndRegister(f5); *oa5 & a; f5.close();
...
What am I doing wrong? Can anybody help?
Note violation of fundamental rule. You have to deserialize the same type you serialized. Here we have: oa << b ... ia >> a This cannot be expected to work. You could do the following oa << statiic_cast<a &>(b); ... ia >> a; I didn't look at f8. Robert Ramey
participants (2)
-
Robert Ramey
-
Shipa