提升序列化未注册类错误

Boost serialization unregistered class errors

本文关键字:错误 注册 升序 序列化      更新时间:2023-10-16

我似乎无法获得 boost::序列化以正常工作。在包含类和存档标头后,我已经在类.cpp文件中撒上了BOOST_CLASS_EXPORT_GUID宏,但我仍然得到unregistered_class例外。

环顾四周,似乎我能找到的都是 1. 要么过时,处理旧版本的库,要么 2. 仅适用于简单的单文件解决方案,其中所有可序列化类都是一个接一个地定义的。我发现没有任何帮助。

我目前的解决方案包括一个编译成静态库的项目,其中包含具有基本可归档类的核心功能,以及另一个最终将充实到更具体的逻辑层中的测试项目。让所有东西都使用 boost::序列化被证明是一场噩梦。我几乎想自己写。

无论如何,引发异常的相关类是在标头中定义的,如下所示:

#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;

其中objectsObject S的std::listObject 是所有事物(包括 Component s(都派生的基类。

如果这听起来令人费解,我深表歉意,但只有三层继承,我相信在序列化的想法悄悄出现之前,我有一个整洁有效的架构。

如果你能帮我摆脱非理性unregistered_class例外,我会为你们的灵魂点燃蜡烛!

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

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

静态库和序列化

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

BOOST_CLASS_EXPORT拆分为BOOST_CLASS_EXPORT_KEYBOOST_CLASS_EXPORT_IMPLEMENT似乎有效。