How to implement serialization in C++(C++中如何实现序列化)
问题描述
每当我发现自己需要在 C++ 程序中序列化对象时,我就会回到这种模式:
Whenever I find myself needing to serialize objects in a C++ program, I fall back to this kind of pattern:
class Serializable {
public:
static Serializable *deserialize(istream &is) {
int id;
is >> id;
switch(id) {
case EXAMPLE_ID:
return new ExampleClass(is);
//...
}
}
void serialize(ostream &os) {
os << getClassID();
serializeMe(os);
}
protected:
int getClassID()=0;
void serializeMe(ostream &os)=0;
};
以上在实践中效果很好.但是,我听说这种切换类 ID 是邪恶的,是一种反模式;在 C++ 中处理序列化的标准 OO 方式是什么?
The above works pretty well in practice. However, I've heard that this kind of switching over class IDs is evil and an antipattern; what's the standard, OO-way of handling serialization in C++?
推荐答案
使用类似 Boost Serialization 虽然绝不是标准,但(在大多数情况下)是一个编写得非常好的库,可以为您完成繁重的工作.
Using something like Boost Serialization, while by no means a standard, is a (for the most part) very well written library that does the grunt work for you.
上次我必须手动解析带有清晰继承树的预定义记录结构时,我最终使用了 带有可注册类的工厂模式(即使用键映射到(模板)创建者函数而不是大量开关函数)来尝试避免您遇到的问题.
The last time I had to manually parse a predefined record structure with a clear inheritance tree, I ended up using the factory pattern with registrable classes (i.e. Using a map of key to a (template) creator function rather than a lot of switch functions) to try and avoid the issue you were having.
编辑
上一段提到的对象工厂的基本 C++ 实现.
EDIT
A basic C++ implementation of a object factory mentioned in the above paragraph.
/**
* A class for creating objects, with the type of object created based on a key
*
* @param K the key
* @param T the super class that all created classes derive from
*/
template<typename K, typename T>
class Factory {
private:
typedef T *(*CreateObjectFunc)();
/**
* A map keys (K) to functions (CreateObjectFunc)
* When creating a new type, we simply call the function with the required key
*/
std::map<K, CreateObjectFunc> mObjectCreator;
/**
* Pointers to this function are inserted into the map and called when creating objects
*
* @param S the type of class to create
* @return a object with the type of S
*/
template<typename S>
static T* createObject(){
return new S();
}
public:
/**
* Registers a class to that it can be created via createObject()
*
* @param S the class to register, this must ve a subclass of T
* @param id the id to associate with the class. This ID must be unique
*/
template<typename S>
void registerClass(K id){
if (mObjectCreator.find(id) != mObjectCreator.end()){
//your error handling here
}
mObjectCreator.insert( std::make_pair<K,CreateObjectFunc>(id, &createObject<S> ) );
}
/**
* Returns true if a given key exists
*
* @param id the id to check exists
* @return true if the id exists
*/
bool hasClass(K id){
return mObjectCreator.find(id) != mObjectCreator.end();
}
/**
* Creates an object based on an id. It will return null if the key doesn't exist
*
* @param id the id of the object to create
* @return the new object or null if the object id doesn't exist
*/
T* createObject(K id){
//Don't use hasClass here as doing so would involve two lookups
typename std::map<K, CreateObjectFunc>::iterator iter = mObjectCreator.find(id);
if (iter == mObjectCreator.end()){
return NULL;
}
//calls the required createObject() function
return ((*iter).second)();
}
};
这篇关于C++中如何实现序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++中如何实现序列化
基础教程推荐
- 从 std::cin 读取密码 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01