我尝试序列化一个类,比如B(在文件b.h中),它是从另一个派生的,比如A(在文件a.h中)。这两个类都有私有成员,我想用非侵入式的boost序列化序列化这两个类。到目前为止,A的序列化/反序列化确实有效。对于派生类的相同,可以使用
ar & boost::serialization::base_object<base_class>(*this);
当使用侵入式方法时,但是将它放在非侵入式的情况下(保存/加载/序列化还是全部三种?)? 必须使用哪个对象代替这个指针?
在生产代码中,我派生的类比B更复杂。我得到了一个编译器错误,我无法在这个小例子中重现。编译器消息(MSVC 2015,C2665,翻译成英文):
'boost :: serialization :: save':没有number1重载可以从类型'type'转换参数number2
德语错误:
Fehler C2665“boost :: serialization :: save”:Durch keine der3Überladungenkontentenalle 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;
}
答案 0 :(得分:1)
首先,关于Quasi-Classes (PDF)的公正警告。他们是封装的敌人并混淆OOP。
接下来,让我快速回答您的两个问题并继续展示我对此的看法:
问。将其置于非侵入式案例中(保存/加载/序列化或全部三种?)?
serialize
或save
和load
中的serialize
(如果您有拆分实施)
问。必须使用哪个对象来代替this指针?
同一个对象。如果你做成员函数this
#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; }
};
指向同一个对象,则传递自由函数作为第二个参数。只需使用该对象。
现在,让我参考我对Get private data members for non intrusive boost serialization C++
的回答以下是Tanner在his comment
中提出的想法的演示<强> Live On WandBox 强>
A.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; }
};
b.h
#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>();
}
的main.cpp
22 serialization::archive 15 0 1 0
0 747
22 serialization::archive 15 1 1 B 1 0
0 1 0
1 42 747
注意它简化了一些事情,并且在没有例外时至少消除了内存泄漏。
# Max Channels is the maximum number of channels to allow on the ordering
# network. When set to 0, this implies no maximum number of channels. MaxChannels: 0
答案 1 :(得分:0)
现在我明白了:带有pimpl样式结构的非侵入式序列化(文本格式),如第3段here所述,让大多数成员都是私有的,并减少了get / set方法的开销。 xml仍处于打开状态 - 在Visual Studio 2015上遇到编译器错误C2664和C2789。此外,json可能很有趣......