serialization.h

xiaoxiao2021-02-27  170

本人水平有限,又不对之处请见谅。

这是一个序列化的头文件,该文件声明了多个结构体,我会从这几个结构体来逐步分析来解析这个头文件。

源码

-源码246——250行 结构体 bool_

template <bool C_> struct bool_ { static const bool value = C_; typedef bool value_type; };

用模版的方式定义了一个结构体。

bool_<true> a;

a.value的值为true。

bool_<false> b;

b.value的值为false。

-源码253——255行 ArchiveBase

class ArchiveBase { public: void* getObject() { return object_; } void setObject(void* object) { object_ = object; } private: void* object_; };

这是flann库的文档基类,主要用于对对象进行序列化,大家将到后面看到其如何使用。 其中 void* object_; 是指向文件的指针。

-源码266——281 InputArchiive

template<typename Archive> class InputArchive : public ArchiveBase { protected: InputArchive() {}; public: typedef bool_<true> is_loading; typedef bool_<false> is_saving; template<typename T> Archive& operator& (T& val) { Serializer<T>::load(*static_cast<Archive*>(this),val); return *static_cast<Archive*>(this); } };

该类继承于ArchiveBase,如其名字InputArchive,它的主要作用是加载对象,对于一个输入的文档,所以is_loading值为true,is_saving值为false,该类重载了一个操作符&。该类也是一个基类,并不适合实例化。

-源码284——299 OutputArchive

template<typename Archive> class OutputArchive : public ArchiveBase { protected: OutputArchive() {}; public: typedef bool_<false> is_loading; typedef bool_<true> is_saving; template<typename T> Archive& operator& (const T& val) { Serializer<T>::save(*static_cast<Archive*>(this),val); return *static_cast<Archive*>(this); } };

OutputArchive继承于ArchiveBase,不同于InputArchive的是。该类是用于save的,所以is_loading.value为false,is_saving.value值为true.用法同InputArchive。

注:这两个类都直接用,一般都作为基类。

-源码303——334 SizeArchive

class SizeArchive : public OutputArchive<SizeArchive> { size_t size_; public: SizeArchive() : size_(0) { } template<typename T> void save(const T& val) { size_ += sizeof(val); } template<typename T> void save_binary(T* ptr, size_t size) { size_ += size; } void reset() { size_ = 0; } size_t size() { return size_; } };

我暂且称其类为尺寸文档。它比OutputArchive多了一个存储size的功能,并针对size提供了一些操作。

-源码355——396

class SaveArchive : public OutputArchive<SaveArchive> { FILE* stream_; bool own_stream_; public: SaveArchive(const char* filename) { stream_ = fopen(filename, "w"); own_stream_ = true; } SaveArchive(FILE* stream) : stream_(stream), own_stream_(false) { } ~SaveArchive() { if (own_stream_) { fclose(stream_); } } template<typename T> void save(const T& val) { fwrite(&val, sizeof(val), 1, stream_); } template<typename T> void save(T* const& val) { // don't save pointers //fwrite(&val, sizeof(val), 1, handle_); } template<typename T> void save_binary(T* ptr, size_t size) { fwrite(ptr, size, 1, stream_); } };

该类SaveArchive继承与OutputArchive,它提供并实现了对对象save的接口。 成员变量:FILE * stream; 指向存储的文件 bool own_stream_;指明该文件指针是否独享 方法: save(const T& val); 将值存储到指定文件中 save_binary(T *ptr, size_t size); 存储一个数据块,首地址为ptr,大小为size个字节。

class LoadArchive : public InputArchive<LoadArchive> { FILE* stream_; bool own_stream_; public: LoadArchive(const char* filename) { stream_ = fopen(filename, "r"); own_stream_ = true; } LoadArchive(FILE* stream) : stream_(stream), own_stream_(false) { } ~LoadArchive() { if (own_stream_) { fclose(stream_); } } template<typename T> void load(T& val) { size_t ret = fread(&val, sizeof(val), 1, stream_); if (ret!=1) { throw FLANNException("Error loading from file"); } } template<typename T> void load(T*& val) { // don't load pointers //fread(&val, sizeof(val), 1, handle_); } template<typename T> void load_binary(T* ptr, size_t size) { size_t ret = fread(ptr, size, 1, stream_); if (ret!=1) { throw FLANNException("Error loading from file"); } } };

原理同SaveArchive不过LoadArchive执行的是加载操作。

回过头来,我们来看一看它是如何进行序列化操作的。 大家注意到,InputArchive,OutputArchive都重载了操作符&,所以我们可称为&为序列化操作符,它们执行时分别调用了Serializer中的静态成员函数load与save,下面我们来仔细看看这Serializer结构体,如何实现这两个函数。

作者是用模版的方式实现了Serializer

大家阅读源码前一部分会发现,除了对vector,Map这两个类型的Serializer,其他类型的Serializer直接调用了Archive类中的相关函数,所以大家理解之前Archive中的相关函数,就能很好的理解。

而对应vector,Map这两种类型需要对其每个元素进行序列化,所以才与原先的有所不同,我认为仔细读代码的人都能很清楚了理解Serilizer的句法,我这就不多赘述了,我是为了帮同我一样的新手来更容易理解serialization.h这个头文件才写的这篇博客。

转载请注明原文地址: https://www.6miu.com/read-12562.html

最新回复(0)