2012-01-11 17 views
1

boost serializeで派生クラスへのポインタを逆シリアル化しようとすると、奇妙な問題が発生します。私はベースを持っており、それらの外に(非侵入型の)セーブ/ロード関数で派生しましたが、ポインタを逆シリアル化しようとするたびに、 "入力ストリームエラー"例外または "未登録のクラス"例外が発生します。ここで私は何をすべきかです:ブーストを使用して派生クラスへのポインタを逆シリアル化する問題: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、私はドキュメント

から借りロードヘルパー/保存最後に
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

そのために、私はこれを行う方法を見つける必要があります:)申し訳ありませんが、私は全く新しいです。 P.S.それは私が次の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)); 

でありません問題を解決してください。

サイドノート - 私は、ストリーム入力エラー ""が発生する可能性のある別のタイプの奇妙なエラーを発見しました。

変数に任意の変数を初期化できますが、そうしないコンストラクタが1つでも存在する場合、デシリアライズしようとするとストリーム入力エラーが発生します。

クラスに変数がない場合はすべてOKです。しかし、1つでもあれば、そのクラスのコンストラクタで少なくとも1つの変数を初期化しなければなりません!なぜこのことが重要なのか分かりませんが、これは私にとって大きな問題を解決しました。

+0

実際、基本クラスのコンストラクタで何かを初期化しないと何が起こるか説明したいと思っています。つまり、私はまだそれを明示的に以下のように呼んでいます:Base()...それには何も実行されていないので、最適化されていますか? – Zeks

+3

ブーストは強力ですが、ええ。私は最後の2時間を派生クラスのシリアライズに費やしました。チュートリアル/本を読んでもうまくいきませんでした。あなたの記事は私のコンパイルエラーを解決しました。まだ何も考えていない**公式のチュートリアルでさえこのライブラリの適切な使用法を示すことができない理由** – emesx

+2

実際には、この質問(重要なことは言及していません)は繰り返しです。私はブーストから新しい何かを使用しようとするたびにこれを得る> _ <まだ...それは私がそれが価値があることを知っているので、私が何度も何度も遭遇するのに十分強力です:) – Zeks