2016-03-01 4 views
0

Я пытаюсь сериализовать производный класс, который не имеет конструктора по умолчанию. Я использую шаблон десериализации. Я прочитал, что вам нужно зарегистрировать тип производного класса, поэтому я делаю это в выходном архиве (outputArchive.register_type<Point>();). Однако при попытке зарегистрировать один и тот же тип с входным архивом я получаю ошибку компилятора, которая говорит, что Point не имеет конструктора по умолчанию (которого нет). Что мы будем делать в этом случае?Зарегистрировать тип без конструктора по умолчанию

#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/serialization/shared_ptr.hpp> 
#include <boost/serialization/base_object.hpp> 

#include <fstream> 

class AbstractPoint 
{ 
public: 
    virtual ~AbstractPoint(){} 
    virtual void DoSomething() = 0; 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     // do nothing 
    } 
}; 

class Point : public AbstractPoint 
{ 
public: 

    Point(const double data) : mData(data) {} 

    void DoSomething(){} 

    template<class TArchive> 
    Point(TArchive& archive) 
    { 
     archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     // Without this, we get unregistered void cast 
     archive & boost::serialization::base_object<AbstractPoint>(*this); 

     archive & mData; 
    } 

    double mData; 
}; 

int main() 
{ 
    std::shared_ptr<AbstractPoint> point(new Point(7.4)); 

    std::ofstream outputStream("test.txt"); 
    boost::archive::text_oarchive outputArchive(outputStream); 
    outputArchive.register_type<Point>(); 
    outputArchive << point; 
    outputStream.close(); 

    std::ifstream inputStream("test.txt"); 
    boost::archive::text_iarchive inputArchive(inputStream); 
    //inputArchive.register_type<Point>(); // Compiler error: no Point::Point() 
    std::shared_ptr<AbstractPoint> pointRead(new Point(inputArchive)); 

    Point* castedPoint = dynamic_cast<Point*>(pointRead.get()); 
    std::cout << "Data: " << castedPoint->mData << std::endl; 
    return 0; 
} 
+1

FYI Я разделил этот вопрос между здесь и http://stackoverflow.com/questions/35753953/common-confusions-with-serializing-polymorphic-types –

ответ

0

В том случае, когда тип не имеет конструктор по умолчанию, вы можете использовать save_construct_data и load_construct_data.

Обратите внимание, что это будет только когда-либо применяются при сериализации через указатели (по очевидным причинам).

Примеры здесь: boost serialization of non-default constructible types и more

+0

я узнал, другой (http://stackoverflow.com/questions/35722135/deserializing-construtor-doesnt-read-data-correctly), что я должен использовать шаблон десериализации конструктора. Итак, вы говорите, что этот шаблон работает, когда не сериализует указатели полиморфного типа? –

+0

@DavidDoria как ваш код вопроса, так и код ответа кажутся типичным для меня кодом Serialization Boost. Код вопроса нарушен по причинам, указанным в ответе. Я испытываю соблазн сказать, что код ответа по-прежнему не прав (трудно заставить его работать надежно, я даже не могу придумать, как его сочетать с сериализацией контейнеров Boost). Так что да, этот ответ не ответил на ваш реальный вопрос, потому что тогда вы задавали неправильный вопрос. – sehe

+0

Точка не использования 'save/load_construct_data' состояла в том, что если у вас нет/требуется указатель, вам не нужно« подделывать », как если бы вы указали указатель, чтобы выполнить сериализацию. –