c++编解码封装

多态版编解码

对服务器和客户端的结构体进行序列化然后对数据进行反序列化

案例分析

在这里插入图片描述

代码demo

Codec.h
#pragma once
#include <iostream>class Codec
{
public:Codec();virtual std::string encodeMsg();//string是标准库的string类virtual void* decodeMsg();virtual ~Codec();
};
RequesetCodec.h
#pragma once
#include "Codec.h"
#include "Message.pb.h"
#include <iostream>
using namespace std;struct RequestInfo
{//默认私有的int cmd;string clientID;string serverID;string sign;string data;
};class RequestCodec : public Codec
{
public://空对象RequestCodec();//解码RequestCodec(string encstr);//序列化后的字符串//编码RequestCodec(RequestInfo* info);//init函数给空构造准备的//解码void initMessage(string encstr);//编码void initMessage(RequestInfo* info);//重写父类函数 -> 序列化函数 -> 序列化的字符串string encodeMsg();//重写父类函数 -> 反序列化函数 -> 返回的是结构体/类对象void* decodeMsg();~RequestCodec();private://保存解码的字符串string m_encStr;//接收编码//要序列化的数据在这个类中,通过这个类进行序列化操作RequestMsg m_msg;//protobuf结构体
};
RequesetCodec.h
#include "RequesetCodec.h"
//空对象
RequestCodec::RequestCodec()
{}
//解码
RequestCodec::RequestCodec(string encstr)
{initMessage(encstr);
}
//编码
RequestCodec::RequestCodec(RequestInfo* info)
{initMessage(info);
}
//init函数给空构造准备的
//解码
void RequestCodec::initMessage(string encstr)
{m_encStr = encstr;
}
//编码
void RequestCodec::initMessage(RequestInfo* info)
{m_msg.set_cmdtype(info->cmd);m_msg.set_clientid(info->clientID);m_msg.set_serverid(info->serverID);m_msg.set_sign(info->sign);m_msg.set_data(info->data);
}
//重写父类函数 -> 序列化函数 -> 序列化的字符串
string RequestCodec::encodeMsg()
{string output;m_msg.SerializeToString(&output);return output;
}
//重写父类函数 -> 反序列化函数 -> 返回的是结构体/类对象
void* RequestCodec::decodeMsg()
{m_msg.ParseFromString(m_encStr);return &m_msg;
}
RequestCodec::~RequestCodec()
{}
test.cpp

触发多态:

#include<iostream>
using namespace std;
#include"Codec.h"
#include"RequesetCodec.h"
#include"RespondCodec.h"
//编码
string encodeMsg(Codec* codec)
{return codec->encodeMsg();
}
//解码
void* decodeMsg(Codec* codec)
{return codec->decodeMsg();
}
int main()
{RequestInfo reqInfo;reqInfo.cmd = 9;reqInfo.clientID = "Onepiece";reqInfo.serverID = "Luffy";reqInfo.data = "我是要成为海贼王的男人";reqInfo.sign = "hahahahahahaha";RequestCodec req(&reqInfo);//编码string reqmsg = encodeMsg(&req);//解码RequestCodec reql(reqmsg);RequestMsg* reqMsg = (RequestMsg*)decodeMsg(&reql);cout << "cmdtype: " << reqMsg->cmdtype()<< ", clientID: " << reqMsg->clientid()<< ", serverID: " << reqMsg->serverid()<< ", data: " << reqMsg->data()<< ", sign: " << reqMsg->sign() << endl;RespondInfo resInfo;resInfo.status = false;resInfo.clientID = "黑崎一护";resInfo.serverID = "朽木露琪亚";resInfo.data = "死神";resInfo.seckeyID = 666;RespondCodec res(&resInfo);//编码string resmsg = encodeMsg(&res);//解码RespondCodec resl(resmsg);RespondMsg* resMsg = (RespondMsg*)decodeMsg(&resl);cout << "cmdtype: " << resMsg->status()<< ", clientID: " << resMsg->clientid()<< ", serverID: " << resMsg->serverid()<< ", data: " << resMsg->data()<< ", sign: " << resMsg->seckeyid() << endl;
}

在这里插入图片描述

工厂模式版编解码

工厂模式(用到多态)

工厂模式的作用

工厂模式的作用是用来创建对象的,那么创建对象的工作实际上是交给了某一个去做。

简单工厂模式–只需1个工厂类

工厂: 使用一个单独的类来做创建实例的过程, 这就是工厂。
简单工厂:把对象的创建放到一个工厂类中,通过参数来创建不同的对象。
特点:

  • 缺点:每添一个对象,就需要对简单工厂进行修改(尽管不是删代码,仅仅是添一个switch case,但仍然违背了“不改代码”的原则)
  • 优点:去除了与具体产品的依赖, 实现简单。
# 简单工厂模式的使用:
1. 创建一个工厂类
2. 在这个类中提供一个公共的成员方法- 创建对象, 一般情况下创建某些实现多态的子类对象- 返回这个对象的地址

案例

// 通过创建工厂类, 添加工厂函数, 创建对象
// 两个编解码的子类
class RequestCodec : public Codec	// 编解码请求数据
class RespondCodec : public Codec	// 编解码响应数据
/*知识点:做条件判断的时候, if..else if .. else 效率比 switch 低如果判断的情况比较少使用 if .. else如果情况比较多, 建议使用 switch
*/
// 创建工厂类, 创建编解码对象
//demo1
class Factory
{
public:Factory();~Factory();// 工厂函数, 创建对象// flag==1 -> RequestCodec// flag==2 -> RespondCodecCodec* createObject(int flag){// 判断if(flag == 1){RequestCodec* req = new RequestCodec();return req;}else if(flag == 2){RequestCodec* res = new RespondCodec();return res;}}
}
//demo2
class Factory
{
public:Factory();~Factory();// 工厂函数, 创建对象// flag==1 -> RequestCodec// flag==2 -> RespondCodecCodec* createObject(int flag){Codec* c = NULL;// 判断if(flag == 1){c = new RequestCodec();}else if(flag == 2){c = new RespondCodec();}return c;}
}

工厂类的使用:

// 1. 创建工厂类对象
Factory* fac = new Factory;
// 2. 通过工厂函数创建编解码对象
Codec* c = fac->createObject(1);
// 3. 编码
string str = c->encoceMsg();

上面这个案例并没有满足需求,假设子类又多了一个,又要在工厂类进行添加---->这是改原来写好的代码

工厂模式–需要N个工厂类

工厂方法:每种产品由一种工厂来创建,一个工厂保存一个new
特点:基本完美,完全遵循 “不改代码”的原则

# 工厂模式流程
1. 创建一个工厂类的基类
2. 在这个基类中定义一个虚函数 -> 创建对象的方法
3. 创建子工厂类(编解码的基类有多少子类, 就创建多少个子工厂类)- 每个编解码的子类, 都对应一个工厂类
4. 在子工厂类中重写工厂类基类中的虚函数

工厂类的使用:

// 两个编解码的子类
class RequestCodec : public Codec
class RespondCodec : public Codec
class TestCodec : public Codec	// 编解码响应数据

使用:

// 创建工厂类的基类
class BaseFactory
{
public:BaseFactory();~BaseFactory;virtual Codec* createObject(){return NULL;}
}
// 工厂类子类
class RequestFactory : public BaseFactory
{
public:RequestFactory();~RequestFactory;Codec* createObject(){return new RequestCodec;}
}
class RespondFactory : public BaseFactory
{
public:RespondFactory();~RespondFactory;Codec* createObject(){return new RespondCodec;}
}
class TestFactory : public BaseFactory
{
public:TestFactory();~TestFactory;Codec* createObject(){return new TestCodec;}
}

这样就不需要修改原来的代码,只需要添加新的子类就行了
工厂模式使用

// 1. 创建工厂类对象
BaseFactory* fac = new RespondFactory;
// 2. 得到了编解码对象
Codec* c = fac->createObject();
// 3. 编码
string str = c->encodeMsg();

工厂模式实况

工厂类的基类 demo

#pragma once
#include "Codec.h"class CodecFactory
{
public:CodecFactory();virtual Codec* createCodec();virtual ~CodecFactory();
};

工厂类的子类.h demo

#pragma once
#include "CodecFactory.h"
#include "Codec.h"
#include "RequesetCodec.h"
#include <iostream>class RequestFactory : public CodecFactory
{
public:RequestFactory(std::string enc);RequestFactory(RequestInfo* info);Codec* createCodec();~RequestFactory();private:bool m_flag;std::string m_encStr;RequestInfo* m_info;
};

工程类的子类.cpp demo

#include "RequestFactory.h"
RequestFactory::RequestFactory(std::string enc) //: CodecFactory()
{m_flag = false;m_encStr = enc;
}
RequestFactory::RequestFactory(RequestInfo* info)//:CodecFactory()
{m_flag = true;m_info = info;
}
Codec* RequestFactory::createCodec()
{Codec* codec = NULL;if (m_flag){codec = new RequestCodec(m_info);}else{codec = new RequestCodec(m_encStr);}return codec;
}
RequestFactory::~RequestFactory()
{}

main.cpp

#include <iostream>
#include "RespondCodec.h"
#include "RespondCodec.h"
#include "Codec.h"
#include "RequestFactory.h"
#include "RespondFactory.h"
using namespace std;int main()
{// 数据编码RequestInfo info{ 1, "client", "server", "x00911", "hello, world" };//结构体初始化CodecFactory* factory = new RequestFactory(&info);Codec* codec = factory->createCodec();string str = codec->encodeMsg();cout << "序列化数据: " << str << endl;delete factory;delete codec;// 数据解码factory = new RequestFactory(str);codec = factory->createCodec();RequestMsg* r1 = (RequestMsg*)codec->decodeMsg();cout << "cmdtype: " << r1->cmdtype()<< ", clinetID: " << r1->clientid()<< ", serverID: " << r1->serverid()<< ", sign: " << r1->sign()<< ", data: " << r1->data() << endl;delete factory;delete codec;cout << endl << "=========================" << endl;RespondInfo resinfo{ 1, 999, "luffy", "zoro", "change world 666 !" };factory = new RespondFactory(&resinfo);codec = factory->createCodec();str = codec->encodeMsg();delete factory;delete codec;factory = new RespondFactory(str);codec = factory->createCodec();RespondMsg* r2 = (RespondMsg*)codec->decodeMsg();cout << "status: " << r2->status()<< ", seckeyID: " << r2->seckeyid()<< ", clinetID: " << r2->clientid()<< ", serverID: " << r2->serverid()<< ", data: " << r2->data() << endl;delete factory;delete codec;return 0;
}

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

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

相关文章

Android 圆形进度条CircleProgressView 基础版

一个最基础的自定义View 圆形进度条&#xff0c;可设置背景色、进度条颜色&#xff08;渐变色&#xff09;下载进度控制&#xff1b;可二次定制度高&#xff1b; 核心代码&#xff1a; Overrideprotected void onDraw(NonNull Canvas canvas) {super.onDraw(canvas);int mW g…

SSH登录介绍

说明&#xff1a;一般登录服务器&#xff0c;我们可以用远程连接工具&#xff0c;如XShell、Windterm等&#xff0c;或者通过公司搭建的JumpServer&#xff08;跳板机、堡垒机&#xff09;来连接。前者是点对点登录&#xff0c;输入主机、端口&#xff0c;通过SSH协议登录&…

ValueError: Object arrays cannot be loaded when allow_pickle=False

文章目录 问题解决方法1&#xff1a;allow_pickleTrue解决方法2&#xff1a;降低numpy版本错误原因&#xff1a;python和numpy版本不兼容 问题 Traceback (most recent call last): File “D:\project\test_st\retrieval\read_npy.py”, line 4, in data np.load(‘mosi0__le…

如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8

如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8 在日常开发中&#xff0c;我们经常会遇到不同编码格式的文件&#xff0c;比如 UTF-8、ASCII、Windows-1252、ISO-8859-1 等。文件编码不一致可能导致读取或处理文件时出现乱码&#xff0c;特别是在批量处理数据文件时。…

【三十八】【QT开发应用】vlcplayer视频播放器(一)实现视频播放,视频暂停,视频停止,进度条调节,音量调节,时长显示功能

效果展示 vlcplayer_test视频播放器 MainWidget.ui 注意控件的布局和命名&#xff0c;控件的命名和信号与槽函数的绑定有关&#xff0c;所以这点很重要。 下载VLC组件和环境配置 videolan下载地址我下载的是vlc-3.0.8-win64版本. 将下载的文件复制粘贴到项目文件中. 复制粘…

【LeetCode每日一题】——1791.找出星型图的中心节点

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 图 二【题目难度】 简单 三【题目编号】 1791.找出星型图的中心节点 四【题目描述】 有一个…

深入了解 美国高防 CN2 :如何提升全球化业务的网络安全与性能

美国高防 CN2 的重要性 在跨国企业和全球化业务的不断扩展下&#xff0c;对高性能和安全的网络连接需求不断增加。美国高防 CN2&#xff08;Global Internet Access&#xff09;以其卓越的跨境传输效率和强大的防护能力&#xff0c;成为许多企业关注的焦点。尤其是对电商、游戏…

Endnote如何关联Word,在Word上通过Endnote插入文献

1、Word版本已被激活 首先检查Word版本是否已经被激活&#xff0c;不管是正版还是破解版&#xff0c;未激活状态&#xff08;试用&#xff09;可能会导致关联不成功。如下图所示为已激活版本&#xff0c;在“文件”—“账户”可看。 2、勾选开发工具 其次&#xff0c;打开Wor…

1688旺铺主页首页装修 代码 首页悬浮视频怎么做?阿里巴巴代码装修悬浮视频代码固定视频悬浮漂浮视频

1688旺铺主页首页装修 代码 首页悬浮视频怎么做&#xff1f;阿里巴巴代码装修悬浮视频代码固定视频悬浮漂浮视频 一秒美工工具

【错误描述:“L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到了一个处理错误”】

解决办法&#xff1a; 一、检查并更改网络协议 &#xff08;如果网络协议更改完成&#xff0c;还是链接失败&#xff0c;直接看 第二点&#xff09; 1、打开网络和Internet 设置 2、找到更改适配器选项 3、先择你要链接VPN&#xff0c;右键选择属性&#xff0c;之后选择安…

基于SSM学生竞赛模拟系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;公告信息管理&#xff0c;试题管理&#xff0c;论坛交流&#xff0c;试卷管理&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;公告…

罗马仕、西圣、安克充电宝哪款品牌更好?综合测评对比谁是TOP.1

罗马仕、西圣、安克充电宝哪款品牌更好&#xff1f;在移动设备日益普及的今天&#xff0c;充电宝已成为许多人的必备配件。市场上涌现出多个知名品牌的充电宝&#xff0c;其中罗马仕、西圣和安克尤为受到消费者的关注。这三个品牌在产品质量、技术创新和用户体验方面各有千秋&a…

spring boot + mybatis + mysql 批量更新报错

问题描述&#xff1a;spring boot mybatis mysql 批量更新报错&#xff0c;如下图所示&#xff1a; mapper文件如下&#xff1a; <!--更新样品项目结果/检验结果内容&#xff0c;提交结果--><update id"submitResult" parameterType"com.weiyu.pojo…

Native Crash 信号速查

重点信号 SIGSEGV&#xff08;11&#xff09; signal segmentation violation&#xff1a;段错误无效内存访问访问无权访问的内存空指针、越界访问&#xff08;mmap&#xff1f;&#xff09; SIGBUS&#xff08;7&#xff09; Bus Error&#xff1a;总线错误非法内存访问访问 …

mac-ubuntu虚拟机(扩容-共享-vmtools)

一、磁盘扩容 使用GParted工具对Linux磁盘空间进行扩展 https://blog.csdn.net/Time_Waxk/article/details/105675468 经过上面的方式后还不够&#xff0c;需要再进行下面的操作 lvextend 用于扩展逻辑卷的大小&#xff0c;-l 选项允许指定大小。resize2fs 用于调整文件系统的…

SQL进阶技巧:巧用异或运算解决经典换座位问题

目录 0 问题描述 1 数据准备 2 问题分析 2.1 什么是异或 2.2异或有什么特性? 2.3 异或应用 2.4 本问题采用异或SQL解决方案 3 小结 0 问题描述 表 seat中有2个字段id和student id 是该表的主键(唯一值)列,student表示学生姓名。 该表的每一行都表示学生的姓名和 ID。…

质数的小游戏~(牛客,cf)

添加链接描述 H 题&#xff1a; n 的范围是 1e6 大致的思路 就是 每一段 固定一个质数&#xff0c;然后这一段中的 数下标 的和都是这个质数。 对于[1 n] 这些数 &#xff0c;对于n 向前找到 一个比他大的最小的质数。假设这个质数nj 。那么也就是说 我n 这个数应该放在下标为…

【热门主题】000018 人工智能深度学习模型:探索与应用

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

Linux学习_8

第七章命令解释器-shell 主要包括Linux中特殊符号&#xff0c;命令别名&#xff0c;命令历史 概述&#xff1a; shell&#xff1a;壳&#xff0c;命令解释器&#xff0c;负责解析用户输入的命令 type命令&#xff1a; 查看命令是内置命令、外置命名、alias命令 type -参数 命…

C++从入门到起飞之——红黑树封装map和set 全方位剖析!

目录 1、map和set的整体框架 2、map和set迭代器的实现 3、map支持[] 4、完整源码 set.h map.h RBTree.h 1、map和set的整体框架 因为map和set的底层都是红黑树&#xff0c;所以我们考虑用一个红黑树的类模版去实例化map和set对象&#xff01;不过&#xff0c;map节点中存…