gpt4 book ai didi

c++ - 使用私有(private)成员 boost 派生类的序列化

转载 作者:行者123 更新时间:2023-11-30 05:09:58 25 4
gpt4 key购买 nike

我尝试序列化一个类,比如 B(在文件 b.h 中),它派生自另一个类,比如 A(在文件 a.h 中)。这两个类都有私有(private)成员,我想以非侵入式的方式使用 boost 序列化库对它们进行序列化。到目前为止,A 的序列化/反序列化确实有效。对于派生类,可以使用

ar & boost::serialization::base_object<base_class>(*this);

当使用侵入式方法时,但是在非侵入式的情况下(保存/加载/序列化还是三者兼而有之?)应该把它放在哪里? 必须使用什么对象代替 this 指针?

在生产代码中,我派生的类比 B 稍微复杂一些。我遇到了一个编译器错误,我无法在这个小示例中重现该错误。编译器消息(MSVC 2015,C2665,英文翻译):

'boost::serialization::save' : none of the number1 overloads can convert parameter number2 from type 'type'

德语错误:

Fehler C2665 "boost::serialization::save": Durch keine der 3 Überladungen konnten alle Argumenttypen konvertiert werden. CalorCLI c:\boost_1_61_0\boost\serialization\split_free.hpp 45

有人能帮忙吗?

a.h 的代码:

#pragma once

class A {
private:
int elemA;

public:
A() = default;
A(int elem) : elemA(elem) {};
virtual ~A() = default;

int getElemA() const { return elemA; }
void setElemA(int elem) {
elemA = elem;
}

};

b.h的代码:

#pragma once
#include "a.h"

class B : public A {
private:
int elemB;

public:
B() = default;
B(int elem) : elemB(elem) {};
virtual ~B() = default;

int getElemB() const { return elemB; }
void setElemB(int elem) { elemB = elem; }

};

主程序代码:

// TestSerialization.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include <string>
#include <fstream>
#include <iostream>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include "b.h"
#include "stdafx.h"

namespace boost {
namespace serialization {

template<class Archive>
void save(Archive & ar, const A & pA, const unsigned int version)
{
ar & pA.getElemA();
}

template<class Archive>
void load(Archive & ar, A & pA, const unsigned int version)
{
int n;
ar & n;
pA.setElemA(n);
}

template<class Archive>
void serialize(Archive & ar, A & pA, const unsigned int version)
{
boost::serialization::split_free(ar, pA, version);
}

template<class Archive>
void save(Archive & ar, const B & pB, const unsigned int version)
{
ar & pB.getElemB();
}

template<class Archive>
void load(Archive & ar, B & pB, const unsigned int version)
{
int n;
ar & n;
pB.setElemB(n);
}

template<class Archive>
void serialize(Archive & ar, B & pB, const unsigned int version)
{
boost::serialization::split_free(ar, pB, version);
}
}
}

int main()
{
A *objA= new A(747);
{
std::ofstream ofs("SavedA");
boost::archive::text_oarchive oa(ofs);
oa << objA;
}

{
A *objA1 = new A();
std::ifstream ifs("SavedA");
boost::archive::text_iarchive ia(ifs);
ia >> objA1;
}

B *objB = new B(747);
{
std::ofstream ofs("SavedB");
boost::archive::text_oarchive oa(ofs);
oa << objB;
}

{
B *objB1 = new B();
std::ifstream ifs("SavedB");
boost::archive::text_iarchive ia(ifs);
ia >> objB1;
}

return 0;
}

最佳答案

首先,关于 Quasi-Classes (PDF) 的公平警告.它们是封装的敌人,混淆了 OOP。

接下来,让我快速回答您的两个问题,并继续展示我对此的看法:

  1. Q. where to put it in the non-intrusive case (save/load/serialize or all three?)?

    要么在serialize 中,要么在saveload 中(如果您有拆分实现)

  2. Q. what object has to been used in place of the this pointer?

    同一个对象。如果您执行成员函数 serialize this 指向与作为第二个参数传递给自由函数的对象相同的对象。只需使用该对象即可。

我的看法

现在,让我引用一下我对 Get private data members for non intrusive boost serialization C++ 的回答

这是 Tanner 在 his comment 中提出的想法的演示

Live On WandBox

  • 啊.h

    #pragma once

    class A {
    private:
    int elemA;

    public:
    A(int elem = 0) : elemA(elem) {};
    virtual ~A() = default;

    int getElemA() const { return elemA; }
    void setElemA(int elem) { elemA = elem; }
    };
  • b.h

    #pragma once
    #include "a.h"

    class B : public A {
    private:
    int elemB;

    public:
    B(int elem = 0) : A(42), elemB(elem) {};

    int getElemB() const { return elemB; }
    void setElemB(int elem) { elemB = elem; }
    };
  • main.cpp

    #include <string>
    #include <sstream>
    #include <iostream>

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/base_object.hpp>
    #include <boost/serialization/export.hpp>
    #include "b.h"

    BOOST_CLASS_EXPORT(A)
    BOOST_CLASS_EXPORT(B)

    namespace privates {

    template <typename Key, typename Key::type PointerToMember> struct store {
    friend typename Key::type get(Key) { return PointerToMember; }
    };

    struct elemA {
    typedef int A::*type;
    friend type get(elemA); // ADL-enable
    };

    struct elemB {
    typedef int B::*type;
    friend type get(elemB); // ADL-enable
    };

    template struct store<elemA, &A::elemA>;
    template struct store<elemB, &B::elemB>;

    } // namespace privates

    auto& getElemA(A& instance) { return instance.*(get(privates::elemA())); }
    auto& getElemB(B& instance) { return instance.*(get(privates::elemB())); }

    namespace boost {
    namespace serialization {
    template<class Archive>
    void serialize(Archive & ar, A& v, unsigned) { ar & getElemA(v); }

    template<class Archive>
    void serialize(Archive & ar, B& v, unsigned) { ar & base_object<A>(v) & getElemB(v); }
    }
    }

    template <typename T> void run_tests() {
    std::stringstream ss;
    {
    A *obj= new T(747);
    boost::archive::text_oarchive oa(ss);
    oa << obj;
    delete obj;
    }

    std::cout << ss.str() << "\n";

    {
    A *obj = nullptr;
    boost::archive::text_iarchive ia(ss);
    ia >> obj;
    delete obj;
    }
    }

    int main()
    {
    run_tests<A>();
    run_tests<B>();
    }

请注意,它简化了一些事情,至少在没有异常时消除了内存泄漏。

输出 Live On WandBox

22 serialization::archive 15 0 1 0
0 747

22 serialization::archive 15 1 1 B 1 0
0 1 0
1 42 747

关于c++ - 使用私有(private)成员 boost 派生类的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45893929/

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