gpt4 book ai didi

c++ - 序列化多态类型的常见混淆

转载 作者:太空狗 更新时间:2023-10-29 20:55:25 24 4
gpt4 key购买 nike

我看过许多涉及序列化派生类的问题、教程和文档,但我未能就几个问题达成共识,包括(并在以下代码中说明):

  • boost::serialization::base_objectBOOST_SERIALIZATION_BASE_OBJECT_NVP
  • archive & mData; 对比 archive & BOOST_SERIALIZATION_NVP(mData);
  • BOOST_SERIALIZATION_ASSUME_ABSTRACT(AbstractPoint); 的用处
  • 要求层次结构中不需要序列化任何内容的类的 serialize()

代码:

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

class AbstractPoint
{
public:
virtual ~AbstractPoint(){}
virtual void DoSomething() = 0;

// Even though the class is abstract, we still need this
template<class TArchive>
void serialize(TArchive& archive, const unsigned int version)
{
// do nothing
}
};

// This doesn't seem to do anything
//BOOST_SERIALIZATION_ASSUME_ABSTRACT(AbstractPoint);

class Point : public AbstractPoint
{
public:
Point() = default;
Point(const double data) : mData(data) {}

void DoSomething(){}

template<class TArchive>
void serialize(TArchive& archive, const unsigned int version)
{
// These two seem equivalent. Without one of them, unregistered void cast
archive & boost::serialization::base_object<AbstractPoint>(*this);
//archive & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AbstractPoint);

// These two seem equivalent
archive & mData;
//archive & BOOST_SERIALIZATION_NVP(mData);
}

double mData;
};

int main()
{
std::shared_ptr<AbstractPoint> point(new Point(7.4));

std::ofstream outputStream("test.txt");
boost::archive::text_oarchive outputArchive(outputStream);
outputArchive.register_type<Point>();
outputArchive << point;
outputStream.close();

std::shared_ptr<AbstractPoint> pointRead;
std::ifstream inputStream("test.txt");
boost::archive::text_iarchive inputArchive(inputStream);
inputArchive.register_type<Point>();
inputArchive >> pointRead;

std::shared_ptr<Point> castedPoint = std::dynamic_pointer_cast<Point>(pointRead);
std::cout << castedPoint->mData << std::endl;
return 0;
}

另一个主要问题是在“真实”环境中(当有链接等时)在哪里注册类,但这似乎值得一个单独的问题。

如果文档中有此类事物的“黄金标准”示例会很棒,但至少在 StackOverflow 上:)

最佳答案

  • boost::serialization::base_object对比BOOST_SERIALIZATION_BASE_OBJECT_NVP

NVP 包装器仅对具有元素命名的存档(如 XML)才需要。

除非你使用它,base_object<>更干净、更简单。

  • archive & mData;对比archive & BOOST_SERIALIZATION_NVP(mData);

同上

  • BOOST_SERIALIZATION_ASSUME_ABSTRACT(AbstractPoint); 的用处

我认为这只是一种优化 - 抑制每个存档类型的注册类型信息,因为您告诉框架它永远不会反序列化该类型的实例

  • 需要 serialize()对于层次结构中不需要序列化任何内容的类。

你不需要它,除非你需要那里关于多态基的类型信息。你什么时候需要那个?当您需要反序列化基类型的指针时。

因此,如果你有

struct A{ virtual ~A(); };
struct B:A{};

struct C:B{};
struct D:B{};`

需要 A 的序列化(但不是 B )如果你(反)序列化 A* .您需要序列化 ​​B如果你(反)序列化 B* .

类似地,如果您的类型不是多态的(虚拟的)或者您不这样使用它,则不需要任何基本序列化(例如,如果您直接(反)序列化 CD)。

最后,如果你有 struct A{}; struct B:A{};根本不需要告诉 Boost Serialization 基本类型(您可以从 B 中进行序列化)。

根据您的样本进行更新:

  1. case1.cpp看起来不错
  2. case2.cpp 当然需要调用基础序列化;不一定使用 base_object 因为你需要多态序列化:

    template<class TArchive> void serialize(TArchive& archive, unsigned) {
    archive & boost::serialization::base_object<AbstractPoint>(*this)
    & mData;
    // OR:
    archive & static_cast<AbstractPoint&>(*this)
    & mData;
    // OR even just:
    archive & mParentData
    & mData;
    }
  3. case3.cpp : 事实上,它与案例 1 完全一样,但具有动态分配和对象跟踪

  4. case4.cpp : 与案例 1 完全一样,但具有动态分配和对象跟踪功能; NB!! 它需要显式序列化 base!

    template<class TArchive> void serialize(TArchive& archive, unsigned) {
    archive & boost::serialization::base_object<AbstractPoint>(*this)
    & mData;
    }
  5. case5.cpp :是的,但使用 CLASS_EXPORT* 更为典型来自 boost/serialization/export.hpp 的宏

Bitrot insurance:

关于c++ - 序列化多态类型的常见混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35753953/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com