注册一个没有默认构造函数的类型

Posted

技术标签:

【中文标题】注册一个没有默认构造函数的类型【英文标题】:Register a type with no default constructor 【发布时间】:2016-03-01 23:07:10 【问题描述】:

我正在尝试序列化没有默认构造函数的派生类。我正在使用反序列化构造函数模式。我读到您必须注册派生类的类型,所以我在输出存档 (outputArchive.register_type<Point>();) 中这样做。但是,当尝试使用输入存档注册相同的类型时,我收到一个编译器错误,提示 Point 没有默认构造函数(它没有)。在这种情况下我们该怎么办?

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

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    
        // do nothing
    
;

class Point : public AbstractPoint

public:

    Point(const double data) : mData(data) 

    void DoSomething()

    template<class TArchive>
    Point(TArchive& archive)
    
        archive >> *this;
    

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    
        // Without this, we get unregistered void cast
        archive & boost::serialization::base_object<AbstractPoint>(*this);

        archive & 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::ifstream inputStream("test.txt");
    boost::archive::text_iarchive inputArchive(inputStream);
    //inputArchive.register_type<Point>(); // Compiler error: no Point::Point()
    std::shared_ptr<AbstractPoint> pointRead(new Point(inputArchive));

    Point* castedPoint = dynamic_cast<Point*>(pointRead.get());
    std::cout << "Data: " << castedPoint->mData << std::endl;
    return 0;

【问题讨论】:

仅供参考,我将这个问题分为这里和***.com/questions/35753953/… 【参考方案1】:

在一个类型没有默认构造函数的情况下,可以使用save_construct_dataload_construct_data

请注意,这些将在通过指针进行序列化时适用(出于显而易见的原因)。

示例如下:boost serialization of non-default constructible types 和 more

【讨论】:

前几天我了解到 (***.com/questions/35722135/…) 我应该使用反序列化构造函数模式。所以你是说这种模式只在不序列化多态类型指针时才有效? @DavidDoria 您的问题代码和答案代码在我看来都是典型的 Boost 序列化代码。由于答案中所述的原因,问题代码已损坏。我很想说答案代码仍然是错误的(很难让它可靠地工作;我什至无法开始思考如何将它与容器的 Boost 序列化结合起来)。所以是的,那个答案没有回答你真正的问题,因为你当时问错了问题。 不使用save/load_construct_data 的要点是,如果您没有/想要一个指针,那么您不需要像拥有/想要一个指针那样“伪造”来做序列化。 @DavidDoria 我猜 Redux 是,Boost Serialization 真的不喜欢非默认构造。就像我说的那样,我知道像这样的“作弊”是如何起作用的,但它永远不会与框架发生冲突

以上是关于注册一个没有默认构造函数的类型的主要内容,如果未能解决你的问题,请参考以下文章

explicit 构造函数

使用杰克逊的 JSON 反序列化:没有找到适合类型的构造函数 - 可以提供默认构造函数或注释构造函数 [重复]

构造函数用于创建类的实例对象,构造函数名应与类名相同,返回类型为void.

Flutter 6种构造函数详解

Qml 注册类型的构造函数中的发射信号不起作用

反序列化没有默认构造函数的类型的 STL 容器