2012-01-11 4 views
1

У меня есть странная проблема, пытающаяся десериализовать указатель на производный класс с форсированием serialize. У меня есть база и выведена с функцией сохранения/загрузки вне их (неинтрузивная версия), но каждый раз, когда я пытаюсь десериализовать указатель, я получаю исключение «Ошибка входного потока» или исключение «Незарегистрированный класс». Вот что я делаю:Проблемы десериализации указателя на производный класс с использованием Boost: serialize

Сначала я определить свои классы:

#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() 
{} 

Тогда я убедиться, что их черты, что мне нужно:

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) 

Далее я определить фактические сохранения функции/нагрузки:

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 

И 2 сохранения/загрузки хелперы я позаимствовал из Docs

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"); 
} 

Что я делаю неправильно? Почему я не могу десериализовать ничего, кроме указателя на базовый класс?

+0

Если вы решили проблему, отправьте решение как _answer_. –

+0

Для этого мне нужно будет найти КАК это сделать :) Извините, я совершенно новый. Постскриптум Кажется, я не смогу опубликовать его в качестве ответа в течение следующих 4 часов - ограничение сайта – Zeks

+0

. Тогда это не решение? Вы сказали, что проблема решена. –

ответ

6

UPD :: После некоторых поисков я еще был в состоянии проследить мою проблему к этому ответу:

boost serialization exception: unregistered class, serializing polymorphic base problem

заменяющего

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

с

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

делает решить проблему.

В качестве побочного примечания - Я нашел еще одну странную ошибку, которая может возникнуть и вызвать «ошибку ввода потока». Он работает следующим образом:

Если в вашей иерархии есть хотя бы один конструктор, который МОЖЕТ инициализировать переменную (любую переменную), но ее нет - вы получите ошибку ввода потока, пытающуюся десериализовать.

Если в классе нет переменных, все в порядке. Но если есть даже один - вы должны инициализировать хотя бы одну переменную в конструкторе этого класса! Я понятия не имею, почему это важно, но это решило для меня серьезную проблему.

+0

На самом деле, я бы очень хотел услышать объяснение, что происходит, когда я не инициализирую ничего в конструкторе базового класса. Я имею в виду - я все еще называю это явным образом: Base() ... он оптимизирован или что-то еще, поскольку в нем нечего делать? – Zeks

+3

Boost мощный, но .. а. Последние 2 часа я потратил на сериализацию производного класса. Чтение учебника/книги не принесло пользы. Ваше сообщение решило мою ошибку компиляции. Все еще не знаю, почему даже официальные учебники не могут показать правильное использование этой библиотеки ** – emesx

+2

На самом деле этот вопрос (повышение, не имеющее полезных примеров/забывание упомянуть о важных вещах) является повторяющимся. Я получаю это близко к каждому моменту, когда я пытаюсь использовать что-то новое из boost> _ Zeks

Смежные вопросы