- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用基类的指针来序列化派生类的对象。下面的代码似乎有效。但我对执行的命令很模糊。输出信息为:
CC连载开始
BB连载开始
AA序列化开始
AA连载结束
BB连载结束
CC连载结束
CC连载开始
BB连载开始
AA序列化开始
AA连载结束
BB连载结束
CC连载结束
class_aa
class_bb
class_cc
由于serialize函数不是virtual的,我想知道为什么CC类的serialize函数会先执行,然后BB,AA的serialize函数。
谢谢
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <string>
#include <boost/serialization/export.hpp>
#include <fstream>
using namespace std;
class AA
{
public:
virtual void foo() = 0;
AA(string aa) :aa_name(aa) { }
AA() {}
template<class Archive>
void serialize(Archive& ar, unsigned int)
{
cout << "AA serialize start" << endl;
ar& aa_name;
cout << "AA serialize end" << endl;
}
string aa_name;
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(AA);
class BB : public AA
{
public:
void foo() {}
virtual void bar() = 0;
BB(string aa, string bb) : AA(aa), bb_name(bb) {}
BB() {}
template<class Archive>
void serialize(Archive& ar, unsigned int)
{
cout << "BB serialize start" << endl;
ar& boost::serialization::base_object<AA>(*this);
ar& bb_name;
cout << "BB serialize end" << endl;
}
string bb_name;
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(BB);
class CC : public BB
{
public:
CC(string aa, string bb, string cc) : BB(aa, bb), cc_name(cc) {}
CC() {}
void bar() {}
template<class Archive>
void serialize(Archive& ar, unsigned int)
{
cout << "CC serialize start" << endl;
ar& boost::serialization::base_object<BB>(*this);
ar& cc_name;
cout << "CC serialize end" << endl;
}
string cc_name;
};
BOOST_CLASS_EXPORT(CC)
int main(int, char const**)
{
AA* obj = new CC("class_aa", "class_bb", "class_cc");
ofstream outfile("archive_test.txt");
boost::archive::text_oarchive out_archive(outfile);
out_archive << obj;
outfile.close();
ifstream infile("archive_test.txt");
boost::archive::text_iarchive ia(infile);
AA* c;
ia >> c;
cout << c->aa_name << endl << dynamic_cast<CC*>(c)->bb_name << endl << dynamic_cast<CC*>(c)->cc_name << endl;
infile.close();
}
最佳答案
Q. since the serialize function is not virtual, I am wondering why the serialize fuction in class CC will execute at first, and then BB, AA's serialize function.
原因是在通过多态引用/指针进行序列化时¹,存档将包含序列化类型的类型 ID,因此库知道要反序列化的类型。
您实际上可以在存档中看到这个:
22 serialization::archive 18 0 0 1 7 Derived 1 0 0 0 0 0 0 8 class_aa8 class_bb 8 class_cc
您可以使用 alternative export macros 控制类型的导出方式。 .
请注意,在上面的示例中,层次结构缺少虚拟析构函数并且存在内存泄漏。后者可能是显而易见的,但前者可能不是²。
这里是
override
, move semantics , =default
ctors/dtors #include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <boost/serialization/serialization.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
class Base {
public:
Base(std::string aa) : aa_name(std::move(aa)) {}
Base() = default;
virtual void foo() const = 0;
virtual ~Base() = default;
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive& ar, unsigned int) {
std::cout << "Base serialize start" << std::endl;
ar& aa_name;
std::cout << "Base serialize end" << std::endl;
}
std::string aa_name;
protected:
void qux() const { std::cout << aa_name << std::endl; }
};
class Middle : public Base {
public:
Middle(std::string aa, std::string Middle) : Base(aa), bb_name(std::move(Middle)) {}
Middle() = default;
void foo() const override { qux(); std::cout << bb_name << std::endl; }
virtual void bar() const = 0;
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive& ar, unsigned int) {
std::cout << "Middle serialize start" << std::endl;
ar& boost::serialization::base_object<Base>(*this);
ar& bb_name;
std::cout << "Middle serialize end" << std::endl;
}
std::string bb_name;
};
class Derived : public Middle {
public:
Derived(std::string aa, std::string bb, std::string cc) : Middle(aa, bb), cc_name(std::move(cc)) {}
Derived() = default;
void bar() const override { foo(); std::cout << cc_name << std::endl; }
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive& ar, unsigned int) {
std::cout << "Derived serialize start" << std::endl;
ar& boost::serialization::base_object<Middle>(*this);
ar& cc_name;
std::cout << "Derived serialize end" << std::endl;
}
std::string cc_name;
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Base)
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Middle)
BOOST_CLASS_EXPORT(Derived)
int main() {
using Ptr = std::unique_ptr<Base>;
{
std::ofstream outfile("archive_test.txt");
boost::archive::text_oarchive out_archive(outfile);
Ptr obj = std::make_unique<Derived>("class_aa", "class_bb", "class_cc");
out_archive << obj;
}
{
std::ifstream infile("archive_test.txt");
boost::archive::text_iarchive ia(infile);
Ptr obj;
ia >> obj;
if (auto cp = dynamic_cast<Derived*>(obj.get()))
cp->bar();
}
}
打印
Derived serialize start
Middle serialize start
Base serialize start
Base serialize end
Middle serialize end
Derived serialize end
Derived serialize start
Middle serialize start
Base serialize start
Base serialize end
Middle serialize end
Derived serialize end
class_aa
class_bb
class_cc
¹ 引用指向一个完全不同的主题:object tracking
² When to use virtual destructors?
对于评论,一些技术分析:
宏 BOOST_CLASS_EXPORT(Derived)
扩展为
namespace boost { namespace serialization {
template <> struct guid_defined<Derived> : boost::mpl::true_ {};
template <> inline const char* guid<Derived>() { return "Derived"; }
} }
namespace boost { namespace archive { namespace detail { namespace extra_detail {
template <> struct init_guid<Derived> {
static guid_initializer<Derived> const& g;
};
guid_initializer<Derived> const& init_guid<Derived>::g =
::boost::serialization::singleton<
guid_initializer<Derived>>::get_mutable_instance()
.export_guid();
} } } }
export_guid()
读取:
guid_initializer const & export_guid() const {
BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value);
// note: exporting an abstract base class will have no effect
// and cannot be used to instantitiate serialization code
// (one might be using this in a DLL to instantiate code)
//BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value);
export_guid(boost::serialization::is_abstract< T >());
return *this;
}
void export_guid(mpl::false_) const {
// generates the statically-initialized objects whose constructors
// register the information allowing serialization of T objects
// through pointers to their base classes.
instantiate_ptr_serialization((T*)0, 0, adl_tag());
}
请注意它如何清楚地说明它只对多态类有意义。 instantiate_ptr_serialization
实际上注册了类型 with all known archives .
无论您的代码组织如何(动态/共享链接、是否有单独的翻译单元),都有大量的模板机制可以让所有东西都实例化(并且只实例化一次)。但最后它转到 register_type
:
template<class T>
const basic_pointer_iserializer *
register_type(T * = NULL){
const basic_pointer_iserializer & bpis =
boost::serialization::singleton<
pointer_iserializer<Archive, T>
>::get_const_instance();
this->This()->register_basic_serializer(bpis.get_basic_serializer());
return & bpis;
}
它在哪里注册pointer_iserializer
:
template<class Archive, class T>
class pointer_iserializer :
public basic_pointer_iserializer
{
private:
virtual void * heap_allocation() const {
detail::heap_allocation<T> h;
T * t = h.get();
h.release();
return t;
}
virtual const basic_iserializer & get_basic_serializer() const {
return boost::serialization::singleton<
iserializer<Archive, T>
>::get_const_instance();
}
BOOST_DLLEXPORT virtual void load_object_ptr(
basic_iarchive & ar,
void * x,
const unsigned int file_version
) const BOOST_USED;
public:
// this should alway be a singleton so make the constructor protected
pointer_iserializer();
~pointer_iserializer();
};
这将实际的新建/删除包装在 heap_allocation
中。为简洁起见,我不在此处包括它,因为我已经在此处对其进行了更详细的分析:How does boost::serialization allocate memory when deserializing through a pointer?
关于C++ boost序列化多态问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62771254/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!