You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost多态序列化已注册类仍报“未注册类”错误求助

解决Boost多态序列化静态库注册失败问题

问题核心

静态库编译场景下,Boost序列化的多态类注册代码会被链接器优化丢弃,导致运行时抛出unregistered class - derived class not registered or exported错误;而共享库场景下因符号默认导出,注册代码可正常执行。

解决方案步骤

1. 标记抽象基类并分离导出声明与实现

Boost序列化要求抽象基类显式声明,同时将导出逻辑拆分为头文件声明和cpp文件实现,避免头文件重复包含问题,同时确保注册代码被正确生成。

修改base.hpp

#pragma once

#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 <boost/serialization/export.hpp>

struct Base
{
    virtual ~Base() = default;

    template <class Archive>
    void serialize(Archive & ar, unsigned /*version*/)
    {
        ar & base_value;
    }

    int base_value;
};

// 标记基类为抽象类,告知序列化系统无需实例化基类
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Base)
// 在头文件声明类的导出
BOOST_CLASS_EXPORT_KEY(Base)

修改base.cpp

#include "base.hpp"

// 在cpp文件实现基类的导出注册
BOOST_CLASS_EXPORT_IMPLEMENT(Base)

修改derived.hpp

#include "base.hpp"

struct Derived : public Base
{
    template <class Archive>
    void serialize(Archive & ar, unsigned /*version*/)
    {
        ar & boost::serialization::base_object<Base>(*this);
        ar & derived_value;
    }

    int derived_value;
};

// 在头文件声明派生类的导出
BOOST_CLASS_EXPORT_KEY(Derived)

修改derived.cpp

#include "derived.hpp"

// 在cpp文件实现派生类的导出注册
BOOST_CLASS_EXPORT_IMPLEMENT(Derived)

2. 强制静态库所有对象被链接

静态库默认只会包含主程序直接引用的符号,而Boost的序列化注册依赖全局对象的构造函数(无直接引用),会被链接器优化丢弃。需通过链接器选项强制包含静态库所有对象。

修改测试程序的CMakeLists.txt

针对GCC/Clang编译器:

target_link_libraries(${mytest} PRIVATE
    # 仅当库为静态时,启用whole-archive选项
    $<$<STATIC:${CMAKE_PROJECT_NAME}_lib>:-Wl,--whole-archive>
    ${CMAKE_PROJECT_NAME}_lib
    $<$<STATIC:${CMAKE_PROJECT_NAME}_lib>:-Wl,--no-whole-archive>
    gtest
)

针对MSVC编译器:

target_link_options(${mytest} PRIVATE
    $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<STATIC:${CMAKE_PROJECT_NAME}_lib>>:/WHOLEARCHIVE:${CMAKE_PROJECT_NAME}_lib>
)

原理说明

  • 抽象类标记:BOOST_SERIALIZATION_ASSUME_ABSTRACT告诉Boost序列化系统基类是抽象的,无需为其生成实例化逻辑,避免多态处理时的错误检查。
  • 分离导出宏:BOOST_CLASS_EXPORT_KEY仅在头文件声明导出信息,BOOST_CLASS_EXPORT_IMPLEMENT在cpp文件生成注册全局对象,既解决头文件重复包含问题,又确保注册代码仅生成一次。
  • 强制链接选项:--whole-archive(GCC/Clang)或/WHOLEARCHIVE(MSVC)强制链接器包含静态库所有对象文件,保证注册用的全局构造函数被执行,完成类的序列化注册。

内容的提问来源于stack exchange,提问作者Elyas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:20:53