开发随笔2-C++对象序列化和反序列化框架

news/2025/11/13 16:55:31/文章来源:https://www.cnblogs.com/audio/p/19218749

View Post

开发随笔2-C++对象序列化和反序列化框架

开发随笔1 - 现代C++对象工厂模式实现 基础之上,我们可以开发一个基于模块工厂的序列化框架。这里采用boost中的property_tree来作为序列化输出和反序列化输入。

 

序列化基类定义如下

class Serializer
{
public:
    virtual ~Serializer() = default;
    virtual PTree serializeThisClass() = 0;
    virtual bool deserializeThisClass(const PTree &node) = 0;
    virtual const char* getClassName()const = 0;
 
    PTree serializeThisClassWithNodeName();
 
    bool saveToFile(const std::string &file);
    bool loadFromFile(const std::string &file);
};

实现如下

PTree Serializer::serializeThisClassWithNodeName()
{
    auto node = serializeThisClass();
    PTree doc;
    doc.add_child(getClassName(),node);
    return doc;
}
 
bool Serializer::saveToFile(const std::string &file)
{
    return savePTreeToFile(serializeThisClassWithNodeName(),file);
}
 
bool Serializer::loadFromFile(const std::string &file)
{
    PTree node;
    if(!readPTreeFromFile(file,node))
        return false;
 
    if(node.empty())
        return false;
 
    auto doc = node.get_child_optional(getClassName());
    if(!doc)
        return false;
    return deserializeThisClass(doc.value());
}

这是一个C++序列化接口类的设计,采用了面向对象的设计模式和模板方法模式。

并定义一系列基础序列化和反序列化函数

void deserialize(const PTree &node,sf::Vector2f& data);
void deserialize(const PTree &node,sf::Vector2i& data);
void deserialize(const PTree &node,sf::Vector2u& data);
void deserialize(const PTree &node,sf::Vector3f& data);
void deserialize(const PTree &node,sf::Vector3i& data);
void deserialize(const PTree &node,sf::IntRect& data);
void deserialize(const PTree &node,sf::FloatRect& data);
void deserialize(const PTree &node,sf::VideoMode& data);
 
PTree serialize(const sf::Vector2f& value);
PTree serialize(const sf::Vector2i& value);
PTree serialize(const sf::Vector2u& value);
PTree serialize(const sf::Vector3f& value);
PTree serialize(const sf::Vector3i& value);
PTree serialize(const sf::IntRect& value);
PTree serialize(const sf::FloatRect& value);

 以及一些辅助类宏定义

#define SERIALIZE_ENUM(node,Enum,value) node.add(#value,enumToString<Enum>(value));
#define SERIALIZE_ITEM(node,value) node.add(#value,value);
#define SERIALIZE_COLOR(node,value) node.add(#value,ColorConverter::toHexString(value));
#define SERIALIZE_NODE(node,value) node.add_child(#value,serialize(value));
#define SERIALIZE_POINTER(node,value) node.add_child(#value,value->serializeThisClassWithNodeName());
 
#define SERIALIZE_SUPER_NODE(node,SuperClass)\
    {\
        auto super = SuperClass::serializeThisClass();\
        node.add_child(#SuperClass,super);\
    }
 
#define DESERIALIZE_ENUM(node,Enum,value)\
    {\
        auto opt = node.get_optional<std::string>(#value);\
        if(opt)\
        {\
            value = stringToEnum<Enum>(*opt,Enum(0));\
        }\
    }
#define DESERIALIZE_ITEM(node,value)\
    {\
        auto opt = node.get_optional<decltype(value)>(#value);\
        if(opt)\
        {\
            value = *opt;\
        }\
    }
#define DESERIALIZE_COLOR(node,value)\
    {\
        auto opt = node.get_optional<std::string>(#value);\
        if(opt)\
        {\
            value = ColorConverter::fromHexString(*opt);\
        }\
    }
#define DESERIALIZE_NODE(node,data)\
    {\
        auto opt = node.get_child_optional(#data);\
        if(opt)\
        {\
            deserialize(opt.value(),data);\
        }\
    }
#define DESERILIZE_SUPER_NODE(node,SuperClass)\
    {\
        auto superName = SuperClass::getClassName();\
        auto opt = node.get_child_optional(superName);\
        if(opt)\
        {\
            SuperClass::deserializeThisClass(*opt);\
        }\
    }
 

对应的反序列化工厂定义如下

class DeserializerFactory : protected ObjectFactory<Serializer, std::string>
{
public:
    using BaseFactory = ObjectFactory<Serializer, std::string>;
    using SerializerPointer = std::shared_ptr<Serializer>;
 
    template<class Target>
    static std::shared_ptr<Target> deserializeFromFile(const std::string& file)
    {
        PTree node;
        if(!readPTreeFromFile(file,node))
        {
            LOG_ERROR("readPTreeFromFile {} failed",file);
            return nullptr;
        }
        return deserialize<Target>(node);
    }
 
    template<class Target>
    static std::shared_ptr<Target> deserialize(const std::string& name, const PTree& node)
    {
        auto option = node.get_child_optional(name);
        if (!option)
        {
            LOG_ERROR("deserialize {} failed",name);
            return nullptr;
        }
 
        auto value = option.value();
        if (value.empty())
            return nullptr;
 
        auto deserializer = BaseFactory::create(name);
        if (deserializer)
        {
            deserializer->deserializeThisClass(value);
            return std::dynamic_pointer_cast<Target>(deserializer);
        }
 
        LOG_ERROR("create object {} failed",name);
        return nullptr;
    }
 
    template<class Target>
    static std::shared_ptr<Target> deserialize(const PTree& node)
    {
        if(node.empty())
        {
            LOG_ERROR("PTree is empty.");
            return nullptr;
        }
 
        auto current = node.begin();
        auto deserializer = BaseFactory::create(current->first);
 
        if(deserializer)
        {
            deserializer->deserializeThisClass(current->second);
            return std::dynamic_pointer_cast<Target>(deserializer);
        }
 
        LOG_ERROR("create object {} failed",current->first);
        return nullptr;
    }
};
 

反序列化工厂继承于对象工厂,提供基于配置文件,指定节点,指定节点下节点名的对象反序列化功能。

使用例子如下

class Entity : public Serializer
{
public:
    PTree serializeThisClass()
    {
        PTree node;
        SERIALIZE_NODE(node,position)
        SERIALIZE_NODE(node,size)
        return node;
    }
    bool deserializeThisClass(const PTree &node)
    {
        DESERIALIZE_NODE(node,position)
        DESERIALIZE_NODE(node,size)
        return true;
    }
    const char *getClassName() const
    {
        return "Entity";
    }
 
    void print()
    {
        std::cout<<position.x<<","<<position.y<<","<<size.x<<","<<size.y<<std::endl;
    }
private:
    sf::Vector2f position;
    sf::Vector2f size;
};
 
REGISTER_PRODUCT(Serializer,Entity)
 
int main()
{
    PTree node;
    readPTreeFromFile("./e.xml",node);
    auto e = DeserializerFactory::deserialize<Entity>(node);
    if(e)
    {
        e->print();
    }
 
    return 0;
}
 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/964478.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年稀土合金直销厂家权威推荐榜单:钢水净化剂/碳钢精炼剂/铸钢精炼剂源头厂家精选

在钢铁工业持续向高质量、低能耗方向发展的背景下,稀土合金凭借其在提升钢水纯净度、改善钢材性能方面的独特优势,正成为冶炼环节不可或缺的添加剂。 稀土合金作为一种由稀土元素与贱金属组合而成的金属材料,能赋予…

C++构造和折构函数详解,超详细! - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Akamai 简单 记录

Akamai 简单 记录2025.11.13找到 sensor_data 的地方``` var TK7 = rB[kY()[mq(S9)].call(null, lg, KG, WF)][kY()[mq(tr)](RC(RC([])), Ax, pO)](RK7); `````` 向上搜索 RK7 RK7 = rB[kY()[mq(S9)].apply(null,…

2025年海南景区标识标牌设计公司权威推荐榜单:海口标识标牌制作/标识标牌制作/安全标识标牌设计源头公司精选

在海南自贸港建设与旅游业升级的双重推动下,景区标识标牌作为游客体验的重要载体,其专业设计与制作正成为景区建设的关键环节。 随着海南旅游市场持续回暖,景区配套设施升级需求显著增长。据行业统计数据显示,2025…

251112D. 谜题(poem)

251112D. 谜题(poem) 给定长为 \(n\) 的排列 \(a\)。有 \(k\) 次交换,每次在所有的 \(\binom n2\) 对数中随机一对交换。问最终逆序对数的期望。 但是这样还不够!有 \(q\) 次修改,将第 \(i\) 次交换改为交换给出的…

可白嫖源码---45125构建个性化智能实习匹配与综合管理平台的研究与构建(案例分析)-附源码

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

同行都在降本,你还在浪费?3招软件许可优化快速追赶!

我是Tom,一线做IT运维已经10年了,看到身边不少同行在软件许可这件事上吃亏,今天我就把我在“许可优化”这条坑上踩过的常识,毫无保留地分享出来,希望能帮到钱没少烧但还在原地踏步的你。 先说说我每次去帮人做系统…

【CSS】background-size 属性详解

【CSS】background-size 属性详解【CSS】background-size 属性详解原创【CSS】background-size 属性详解-CSDN博客于 2024-09-23 11:30:52 发布1.8w 阅读 32 33CC 4.0 BY-SA版权文章标签:#css#前端#node.js#javascrip…

Redis分布式锁:从“能用”到“好用”,中间差了多少细节?

redis分布式锁安全吗? 1、为什么需要分布式锁与分布式锁对应的是【单机锁】,在写多线程时,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来【互斥】,以确保共享变量的正确性,使用范围是在同一个进程中…

为什么你的JavaScript代码总是出bug?这5个隐藏陷阱太坑了!

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣你是不是经常遇到这样的情况:明明代码看起来没问题,一运行就各种报错?或者测试时好好的,上线后用户反馈bug不断?更气人的是,有时候改了一个小问题,结果引…

[电调]AM32电调调参系列 —— Complementary PWM参数的作用与分析

[电调]AM32电调调参系列 —— Complementary PWM参数的作用与分析https://blog.csdn.net/qq_39312146/article/details/153827884在AM32固件中,​​Complementary PWM(互补PWM)​​ 的选择对电调的性能、效率和发热…

Zabbix监控mysl数据库配置

用mysql自带的模板,可以监控如下内容:OPS(增删改查)、mysql请求流量带宽,mysql响应流量带宽,最后会附上相应的监控图! 一、编写脚本 check_mysql.sh vi /usr/local/zabbix/share/check_mysql.sh !/bin/bash ---…

Java 线程同步与线程间通信

Java 线程同步与线程间通信 线程同步概述 核心问题:竞争状态与线程安全 当多个线程同时访问共享资源(临界资源)时,可能导致资源数据被破坏,这种现象称为竞争状态。若一个类的对象在多线程环境中不会引发竞争状态,…

2025年惠州高端中医馆品牌权威推荐榜单:老中医问诊/代煎中药/老中医调理身体品牌精选

在健康惠州战略推进下,高端中医馆已从单纯的诊疗服务向健康管理、特色理疗、文化传承等多元化方向发展,为市民提供全方位中医药服务。 随着居民健康消费水平升级和中医文化复兴,惠州高端中医馆市场正经历从“量变”…

HarmonyOS ArkTS卡片开发:多种方式实现卡片信息刷新

在移动应用生态中,卡片作为重要信息的快捷展示形式,极大地提升了用户体验。HarmonyOS的ArkTS卡片开发为开发者提供了强大的工具,本文将基于CardInfoRefresh示例项目,深入解析ArkTS卡片开发的核心原理与实践。1. Ar…

可视化图解算法68:数组中出现次数超过一半的数字

对于LeetCode数据结构与算法,我们总结了一套【可视化+图解】方法,依据此方法来解决相关问题,算法变得易于理解,写出来的代码可读性高也不容易出错。1.题目 描述 给一个长度为 n 的数组,数组中有一个数字出现的次数…

2025年惠州线下媒体公司权威推荐榜单:楼宇视频广告/社区广告/社区媒体广告源头公司精选

在信息过载的数字时代,线下媒体以其真实的场景触达和稳定的传播效果,正重获品牌方的青睐。 惠州线下媒体市场近年来保持稳定发展态势。据行业调研数据显示,社区媒体广告市场年增长率保持在15%左右,预计2025年惠州地…

题解:P9052 [PA 2021] Areny

好题,但是也没有那么难,感觉难度很大一部分在于读懂题。 题意:给出一个有向图,保证每个点都有一个出度且不为自环,现在求出对于每个 \(1\le k\le n\),满足以下条件的 \((A,B)\) 对有多少个。\(1\le A\le k,A\not…

Copula函数的参数估计与拟合

Copula函数的参数估计与拟合 Copula函数是描述随机变量间相关结构的强大工具,它将边缘分布与变量间的依赖结构分离建模。详细介绍Copula函数的参数估计与拟合方法 Copula理论基础 Copula函数定义 Copula函数是一个多元…