提升序列化未注册的类错误

时间:2013-11-23 17:16:40

标签: c++ serialization boost c++11

我似乎无法使boost :: serialization运行良好。在包含类和归档标题之后,我将类.cpp文件与BOOST_CLASS_EXPORT_GUID宏一起使用了,但我仍然得到unregistered_class例外。

我环顾四周,似乎无论我能找到的是1.过时,处理旧版本的库,或2.仅适用于简单的单文件解决方案,其中所有可序列化的类都定义为在另一个之后。我找不到任何帮助。

我目前的解决方案包括一个项目,编译成静态库,包含基本可存档类的核心功能,以及另一个最终将充实到更具体的逻辑层的测试项目。让一切与boost :: serialization一起工作是一场噩梦。我差点想自己写。

无论如何,引发异常的问题是在标题中定义的,看起来像这样:

#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/serialization.hpp>
// Other includes...

namespace GameCore { class Component; }
//  Forward declare some boost::serialization functions that appear at the bottom.
// ...
BOOST_SERIALIZATION_ASSUME_ABSTRACT(GameCore::Component);

namespace GameCore
{
    // Some forward declares..

//////////////////////////////////////////////////////////////////////////
//  Base component type.
//////////////////////////////////////////////////////////////////////////
class Component : public Updatable, public Object
{
    friend class boost::serialization::access;  

protected:                                  
    template <typename Archive>                 
    friend void boost::serialization::serialize(Archive& archive, Component& object, const unsigned int version);   
    template <typename Archive> friend void boost::serialization::load_construct_data(Archive& archive, Component* t, const unsigned int version);  
    template <typename Archive> friend void boost::serialization::save_construct_data(Archive& archive, const Component* t, const unsigned int version);    

public:
    Component(GameObject& owner);
    virtual ~Component() = 0;

    // Irrelevant stuff..

    GameObject& gameObject;
    Transform* transform;
};
}
//  The component includes have to be placed here because it would otherwise create a cyclic inclusion when trying to compile the 
//  individual component classes, say, Transform, which would end up including itself.
#include "Transform.h"


namespace boost
{
    namespace serialization
    {
        template<class Archive>
        inline void save_construct_data(Archive& archive, const GameCore::Component* t, const unsigned int version)
        {
            archive << t->gameObject;
        }


    template<class Archive>
    inline void load_construct_data(Archive& archive, GameCore::Component* t, const unsigned int version)
    {
        //  Retrieve data from archive required to construct new instance.
        GameCore::GameObject owner;
        archive >> owner;

        //  Invoke inplace constructor to initialize instance of class.
        ::new(t)GameCore::Component(owner);
    }


    //////////////////////////////////////////////////////////////////////////
    //  Serialization function for save/load.
    //////////////////////////////////////////////////////////////////////////
    template <typename Archive>
    void serialize(Archive& archive, GameCore::Component& t, const unsigned int version)
    {
        archive & boost::serialization::base_object<GameCore::Object>(t);
        archive & boost::serialization::base_object<GameCore::Updatable>(t);
        archive & t.gameObject;
        archive & t.transform;
    }
}
}

这是一个头文件。很抱歉。它的.cpp文件如下所示:

#include "Component.h"

#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
// Other includes...

BOOST_CLASS_EXPORT_GUID(GameCore::Component, "GameCore::Component");

// Class method definitions here.

当我尝试从Component归档派生的实例对象时引发异常,std::ofstream outputFile(fileName); boost::archive::text_oarchive outputArchive(outputFile); outputArchive << objects; 本身是一个抽象类。我通过在不同经理类中定义的简单方法进行归档:

objects

其中std::listObject的{​​{1}}。 Object是所有内容(包括Component)派生的基类。

如果这听起来很复杂,我道歉,但只有三层继承,我相信在序列化的想法悄悄进入之前我有一个整洁有效的架构。

如果你能帮助我摆脱不合理的unregistered_class例外情况,我会为你的灵魂点上蜡烛!

更新:有趣的是,Component的所有派生类都没有引发异常。

1 个答案:

答案 0 :(得分:6)

在我的神经元寻找答案后,我偶然发现了文档中的这一行:

  

静态库和序列化

     

数据类型序列化的代码可以保存在库中   它可以用于其余的类型实现。这很好用,而且   可以节省大量的编译时间。只编译序列化   库中的定义。显式实例化序列化代码   对于您打算在库中使用的所有归档类。出口   类型,只在标题中使用BOOST_CLASS_EXPORT_KEY。对于导出类型,   只在编译的定义中使用BOOST_CLASS_EXPORT_IMPLEMENT   图书馆。对于任何特定类型,应该只有一个文件   包含该类型的BOOST_CLASS_EXPORT_IMPLEMENT。这确保了   程序中只存在一个序列化代码副本。它   避免浪费空间和不同版本的可能性   同一程序中的序列化代码。包含   多个文件中的BOOST_CLASS_EXPORT_IMPLEMENT可能会导致a   由于重复的符号或投掷运行时而无法链接   异常。

BOOST_CLASS_EXPORT拆分为BOOST_CLASS_EXPORT_KEYBOOST_CLASS_EXPORT_IMPLEMENT似乎有效。