2012-01-11 4 views
1

부스트 serialize를 사용하여 파생 클래스에 대한 포인터를 비 직렬화하려는 이상한 문제가 있습니다. 내가베이스 및 파생 된 /로드 함수를 외부 (비 관입 버전) 있지만 포인터를 deserialize 할 때마다 "입력 스트림 오류"예외 또는 "등록되지 않은 클래스"예외가 얻을 때마다 파생됩니다.부스트를 사용하여 파생 클래스에 대한 포인터를 비 직렬화하는 문제 : serialize

먼저 내 클래스를 정의 :

BOOST_CLASS_EXPORT_GUID(Base, "Base") 
BOOST_SERIALIZATION_SPLIT_FREE(Base) 
BOOST_CLASS_IS_WRAPPER(Base) 
BOOST_CLASS_TRACKING(Base, boost::serialization::track_selectively) 
BOOST_CLASS_IMPLEMENTATION(Base, boost::serialization::object_class_info) 

BOOST_SERIALIZATION_SPLIT_FREE(Derived) 
BOOST_CLASS_EXPORT_GUID(Derived, "Derived") 
BOOST_CLASS_IS_WRAPPER(Derived) 
BOOST_CLASS_IMPLEMENTATION(Derived, boost::serialization::object_class_info) 
BOOST_CLASS_TRACKING(Derived, boost::serialization::track_selectively) 

다음 내가 실제 저장 /로드 기능을 정의

#include <fstream> 
#include <iomanip> 

#include <boost/archive/xml_iarchive.hpp> 
#include <boost/archive/xml_oarchive.hpp> 
#include <boost/archive/archive_exception.hpp> 
#include "boost/serialization/split_free.hpp" 
#include "boost/serialization/export.hpp" 
#include "boost/serialization/utility.hpp" 
#include <boost/serialization/string.hpp> 
#include <boost/serialization/binary_object.hpp> 

class Base 
{ 
public: 
    bool isEnabled; 
    Base(); 
    virtual ~Base(){} 
}; 
Base::Base() 
{ 
    isEnabled = 0; 
} 

class Derived : public Base 
{ 

public: 
    Derived(); 
    virtual ~Derived(){} 
    int layerHeight; 
}; 
Derived::Derived():Base() 
{} 

그럼 내가 그들의 특성은 내가 필요한 있는지 확인 여기에 내가 할 것입니다 :

namespace boost { 

    namespace serialization { 

    template<class Archive> 
    void save(Archive & ar,const Base& obj, const unsigned int version) 
    { 
     bool isEnabled = obj.isEnabled; 
     ar << BOOST_SERIALIZATION_NVP(isEnabled); 
    } 
    template<class Archive> 
    void load(Archive & ar, Base& obj, const unsigned int version) 
    { 
     bool isEnabled; 
     ar >> BOOST_SERIALIZATION_NVP(isEnabled); 
    } 
    } // namespace serialization 
} // namespace boost 

namespace boost { 
template<> 
struct is_virtual_base_of<Base, Derived>: public mpl::true_ {}; 

namespace serialization { 

template<class Archive> 
void save(Archive & ar,const Derived& obj, const unsigned int version) 
{ 
    ar & boost::serialization::base_object<Base>(obj); 
    int height =obj.layerHeight; 
    ar << BOOST_SERIALIZATION_NVP(height); 
} 
template<class Archive> 
void load(Archive & ar, Derived& obj, const unsigned int version) 
{ 
    ar.template register_type<Base>(); 
    ar.template register_type<Derived>(); 
    ar & boost::serialization::base_object<Base>(obj); 
    int height; 
    ar >> BOOST_SERIALIZATION_NVP(height); 
} 
} // namespace serialization 
} // namespace boost 

그리고이 나는 문서

에서 차용로드 도우미/저장 마지막으로
template <typename T> 
void save_schedule(const T& s, const char * filename){ 
    // make an archive 
    std::ofstream ofs(filename); 
    assert(ofs.good()); 
    boost::archive::xml_oarchive oa(ofs); 
    oa << BOOST_SERIALIZATION_NVP(s); 
} 

template <typename T> 
void restore_schedule(T &s, const char * filename) 
{ 
    // open the archive 
    std::ifstream ifs(filename); 
    assert(ifs.good()); 
    boost::archive::xml_iarchive ia(ifs); 
    // restore the schedule from the archive 
    ia >> BOOST_SERIALIZATION_NVP(s); 
} 

- 여기가 내가 모든

int main(int argc, char *argv[]) 
{ 
    Base* basePointer = new Base(); 
    Base* objectPointer = new Derived(); 
    Derived * secondObjectPointer = new Derived(); 
    Derived justObject; 

    save_schedule(basePointer, "C:\\basePointer.xml"); 
    save_schedule(objectPointer, "C:\\objectPointer.xml"); 
    save_schedule(secondObjectPointer , "C:\\secondObjectPointer.xml"); 
    save_schedule(justObject, "C:\\justObject.xml"); 

    //this works OK 
    restore_schedule(basePointer, "C:\\basePointer.xml"); 

    //this gives "Input Stream Error" 
    restore_schedule(objectPointer, "C:\\objectPointer.xml"); 

    //this gives "Unregistered class" 
    restore_schedule(secondObjectPointer, "C:\\secondObjectPointer.xml"); 

    //This works >__< But I need to serialize pointers so I cannot use this 
    restore_schedule(justObject, "C:\\justObject.xml"); 
} 

내가 뭘 잘못 사용하려고 어떻게? 기본 클래스에 대한 포인터 이외의 다른 요소를 deserialize 할 수없는 이유는 무엇입니까?

+0

문제를 해결 한 경우 솔루션을 _answer_으로 게시하십시오. –

+0

그걸 위해, 나는 이것을 어떻게 해야할지 찾아야합니다 :) 미안 해요, 전 완전히 새로운 것입니다. 추신 다음 4 시간 동안 답변으로 게시 할 수없는 것 같습니다. 사이트 제한 – Zeks

+0

결국 해결책이 아닙니까? 문제가 해결되었다고하셨습니까? –

답변

6

UPD : 좀 더 나는이 대답에 내 문제를 추적 할 수 있었다 검색 한 후 :

// taken from the link above (macro expanded) 
ar & boost::serialization::make_nvp(BOOST_PP_STRINGIZE(obj),boost::serialization::base_object<Base >(obj)); 

가 함께 않습니다

boost serialization exception: unregistered class, serializing polymorphic base problem

//original taken from Boost Docs 
ar & boost::serialization::base_object<Base>(obj); 

교체 문제를 해결하십시오.

사이드 노트 - 이상한 오류가 발생하여 "스트림 입력 오류"가 발생할 수 있습니다..

변수 (변수)를 초기화 할 수있는 ONE 생성자가 하나라도있는 경우 (그렇지 않으면) 직렬화를 시도하는 스트림 입력 오류가 발생합니다.

클래스에 변수가 없으면 모두 정상입니다. 하지만 하나라도 있다면 - 그 클래스의 생성자에서 적어도 하나의 변수를 초기화해야합니다! 왜 이것이 중요한지 잘 모르겠지만 이것이 중요한 문제를 해결해주었습니다.

+0

사실, 기본 클래스의 생성자에서 아무것도 초기화하지 않으면 어떻게되는지 설명을 듣고 싶습니다. 내 말은 - 나는 여전히 그것을 명시 적으로 다음과 같이 부르고 있습니다. Base() ... 그것에서 수행 할 것이 없기 때문에 최적화 된 것이나 다른 것이 있습니까? – Zeks

+3

부스트는 강력하지만, 어. 지난 2 시간 동안 파생 클래스를 직렬화하려고했습니다. 튜토리얼/책을 읽는 것은 좋지 않았다. 귀하의 게시물은 내 컴파일 오류를 해결했습니다. 아직도 모르겠다 ** 공식 튜토리얼조차도이 도서관의 적절한 사용법을 보여주지 못하는 이유 ** – emesx

+2

사실,이 질문은 (유용한 것들이 없거나 중요한 것을 언급하는 것을 잊어 버린) 반복되는 것입니다. 부스트에서 새로운 무언가를 사용하려고 할 때마다 이것을 얻습니다> _ <여전히 ... 그것은 단지 가치가 있음을 알고 있기 때문에 반복해서 넘어지기에 충분히 강력합니다 :) – Zeks

관련 문제