C++ 如何使用boost序列化具有共享\u ptr成员的对象

C++ 如何使用boost序列化具有共享\u ptr成员的对象,c++,serialization,boost,deserialization,C++,Serialization,Boost,Deserialization,有抽象的I1和派生的C1 有抽象的I2和派生的C2 I1拥有共享\u ptr。如何使用boost serializaton使它们可序列化?我正在尝试这样做,但我的应用程序出现异常 #include <sstream> #include <boost/shared_ptr.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_iarchive.hpp

有抽象的
I1
和派生的
C1

有抽象的
I2
和派生的
C2

I1
拥有
共享\u ptr
。如何使用boost serializaton使它们可序列化?我正在尝试这样做,但我的应用程序出现异常

#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    boost::archive::binary_oarchive oa(ss);
    oa.register_type<I1>();
    oa.register_type<C1>();
    oa.register_type<I2>();
    oa.register_type<C2>();

    oa << c2;

    boost::archive::binary_iarchive ia(ss);
    //ia.register_type<I1>(); // cannot instantiate abstract class
    ia.register_type<C1>();
    //ia.register_type<I2>(); // cannot instantiate abstract class
    ia.register_type<C2>();

    ia >> c2;
}
#包括
#包括
#包括
#包括
#包括
结构I1
{
I1(){}
虚拟~I1()=0{}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
}
};
结构C1:I1
{
虚拟~C1(){}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::base_对象(*this);
}
};
结构I2
{
虚拟~I2()=0{}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&p;
}
boost::共享\u ptr p;
};
结构C2:I2
{
C2(){p=boost::shared_ptr(新C1);}
虚拟~C2(){}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::base_对象(*this);
}
};
int main()
{
C2;
std::字符串s;
标准::stringstream ss(s);
boost::archive::binary_oarchive oa(ss);
oa.register_type();
oa.register_type();
oa.register_type();
oa.register_type();
oa>c2;
}
添加

根据文件

更新

我刚刚用VS2013RTM和Boost 1_55进行了验证,它可以正常工作(TM),我已经

  • 删除了抽象基的类型注册(无论如何都不能从存档中具体加载)
  • 增加

    #pragma warning(disable: 4244)
    #include <boost/config/warning_disable.hpp>
    
    #杂注警告(禁用:4244)
    #包括
    
    在文件顶部,以使已知的闲聊警告静音

代码编译并运行时没有错误。要有好的风格,你可能应该

  • 通过指针序列化c2(堆栈变量可以)
以下是我最终得到的完整代码:

#pragma warning(disable: 4244)
#include <boost/config/warning_disable.hpp>
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

int main()
{
    boost::shared_ptr<I2> c2(new C2);

    std::string s;
    std::stringstream ss(s);

    boost::archive::text_oarchive oa(ss);
    oa.register_type<C1>();
    oa.register_type<C2>();

    oa << c2;
    std::cout << "Serialized form: '" << ss.str() << "'\n";

    boost::archive::text_iarchive ia(ss);
    ia.register_type<C1>();
    ia.register_type<C2>();

    ia >> c2;
}
#杂注警告(禁用:4244)
#包括
#包括
#包括
#包括
#包括
#包括
结构I1
{
I1(){}
虚拟~I1()=0{}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
}
};
结构C1:I1
{
虚拟~C1(){}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::base_对象(*this);
}
};
结构I2
{
虚拟~I2()=0{}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&p;
}
boost::共享\u ptr p;
};
结构C2:I2
{
C2(){p=boost::shared_ptr(新C1);}
虚拟~C2(){}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::base_对象(*this);
}
};
int main()
{
boost::共享ptr c2(新c2);
std::字符串s;
标准::stringstream ss(s);
boost::archive::text\u oarchive oa(ss);
oa.register_type();
oa.register_type();

oa我认为您也不应该在输出归档上注册纯虚拟类

或者,您可以使用。定义类后,用以下代码替换其余代码:

#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT(C1)
BOOST_CLASS_EXPORT(C2)

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    {
       boost::archive::binary_oarchive oa(ss);
       oa << c2;
    }

    boost::archive::binary_iarchive ia(ss);
    ia >> c2;
}
#包括
增压级出口(C1)
增压级输出(C2)
int main()
{
C2;
std::字符串s;
标准::stringstream ss(s);
{
boost::archive::binary_oarchive oa(ss);
oa>c2;
}

我将输出存档放在一个单独的块中。我认为它很可能在没有它的情况下工作,但我希望确保所有内容都已刷新(通过超出范围)。

boost序列化文档介绍了有关
boost\u CLASS\u导出的有趣内容:

…促进一流的出口

因此,导出的需要通过使用派生类来暗示,派生类通过指向其基类的指针或引用进行操作

您的
p
指针正是这样做的。将这些宏添加到您的代码中还可以摆脱来自main的难看的显式
register\u type()
调用,这也很好:)

因此,这段代码似乎在VS2014中编译并运行:

#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

BOOST_CLASS_EXPORT(I1)

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

BOOST_CLASS_EXPORT(C1)

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

BOOST_CLASS_EXPORT(I2)

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

BOOST_CLASS_EXPORT(C2)

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    boost::archive::binary_oarchive oa(ss);
    oa << c2;

    boost::archive::binary_iarchive ia(ss);
    ia >> c2;
}
#包括
#包括
#包括
#包括
#包括
#包括
结构I1
{
I1(){}
虚拟~I1()=0{}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
}
};
增压级输出(I1)
结构C1:I1
{
虚拟~C1(){}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::base_对象(*this);
}
};
增压级出口(C1)
结构I2
{
虚拟~I2()=0{}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&p;
}
boost::共享\u ptr p;
};
增压级输出(I2)
结构C2:I2
{
C2(){p=boost::shared_ptr(新C1);}
虚拟~C2(){}
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&boost::serialization::base_对象(*this);
}
};
增压级输出(C2)
int main()
{
C2;
std::字符串s;
标准::stringstream ss(s);
boost::archive::binary_oarchive oa(ss);
oa>c2;
}

不过,有趣的是,Boost docs的声明显然不适用于所有编译器,而且互联网上的许多代码示例在VS2014中都不起作用。

它们需要添加到哪里?我会在接口声明之后立即添加它们classes@Ufx不管它值多少钱,我现在已经在VS2013上对它进行了测试-I didn在其他时间无法访问Windows。也许您应该在一个独立的、新的控制台应用程序中尝试它,以排除项目/生成设置的其余部分出现问题。我刚刚替换了除主函数(和标题)之外的所有函数它仍然崩溃。martin_pr的solusion没有崩溃。你能告诉我们哪个编译器接受
=0{}
语法吗?我知道它存在,但我不知道有哪个编译器能够足够有趣地接受这种输入,你的代码在Linu上的gcc 4.8.1上运行良好
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

BOOST_CLASS_EXPORT(I1)

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

BOOST_CLASS_EXPORT(C1)

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

BOOST_CLASS_EXPORT(I2)

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

BOOST_CLASS_EXPORT(C2)

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    boost::archive::binary_oarchive oa(ss);
    oa << c2;

    boost::archive::binary_iarchive ia(ss);
    ia >> c2;
}