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.rhkb.cn/news/457564.html

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

相关文章

西瓜书《机器学习》符号表KaTex表示

写这篇post的缘故是最近整理机器学习的相关公式&#xff0c;经常要用到KaTex, 但网络上搜索到的西瓜书符号表的表示有些并不准确或不严谨&#xff0c;本着严谨治学的态度&#xff0c;整理了一下符号表的KaTex表示&#xff0c;希望有所帮助,整理过程中参考了《南瓜书》和 KaTex官…

Flutter TextField和Button组件开发登录页面案例

In this section, we’ll go through building a basic login screen using the Button and TextField widgets. We’ll follow a step-bystep approach, allowing you to code along and understand each part of the process. Let’s get started! 在本节中&#xff0c;我们…

软件系统建设方案书(word参考模板)

1 引言 1.1 编写目的 1.2 项目概述 1.3 名词解释 2 项目背景 3 业务分析 3.1 业务需求 3.2 业务需求分析与解决思路 3.3 数据需求分析【可选】 4 项目建设总体规划【可选】 4.1 系统定位【可选】 4.2 系统建设规划 5 建设目标 5.1 总体目标 5.2 分阶段目标【可选】 5.2.1 业务目…

ctfshow(259->261)--反序列化漏洞--原生类与更多魔术方法

Web259 进入界面&#xff0c;回显如下&#xff1a; highlight_file(__FILE__);$vip unserialize($_GET[vip]); //vip can get flag one key $vip->getFlag();题干里还提示了网站有一个flag.php界面&#xff0c;源代码如下&#xff1a; $xff explode(,, $_SERVER[HTTP_X…

Docker容器操作

Docker容器操作 启动容器 docker run -it 镜像名(镜像id) bash当利用docker run来创建容器时&#xff0c;Docker在后台运行的标准操作包括&#xff1a; 检查本地是否存在指定的镜像&#xff0c;不存在就从公有仓库中下载利用镜像创建并启动一个容器分配一个文件系统&#xf…

C语言实现Go的defer功能

之前笔者写了一篇博文C实现Go的defer功能&#xff0c;介绍了如何在C语言中实现Go的defer功能&#xff0c;那在C语言中是否也可以实现这样的功能呢&#xff1f;本文就将介绍一下如何在C语言中实现Go的defer功能。 我们还是使用C实现Go的defer功能中的示例&#xff1a; void te…

医院信息化与智能化系统(9)

医院信息化与智能化系统(9) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应的…

改进YOLOv8系列:引入低照度图像增强网络Retinexformer | 优化低光照目标检测那题

改进YOLOv8系列:引入低照度图像增强网络Retinexformer | 优化低光照目标检测那题 🚀论文研究概括🚀加入到网络中的理论研究🚀需要修改的代码1 🍀🍀Retinexformer 代码2🍀🍀tasks里引用🚀创建yaml文件🚀测试是否创建成功前言:这篇论文提出了一种用于低光图像…

STM32应用详解(10)I2C总线初始化

文章目录 前言一、I2C总线初始化二、程序源码与详解1.I2C初始化2.I2C端口初始化及设置IO端口工作模式3.函数I2C_Init4.函数I2C_Cmd5.使能APB1外设时钟6.I2C通信时序图 前言 介绍STM32的I2C总线初始化&#xff0c;给出了代码详解。《i2c.h》文件&#xff0c;由用户编写。定义了…

系统聚类比较——最短距离法、最长距离法、重心法和类平均法

系统聚类概述 系统聚类&#xff0c;又称分层聚类法&#xff0c;是一种用于分析数据的统计方法&#xff0c;在生物学、分类学、社会网络等领域有广泛应用。以下是对系统聚类的详细概述&#xff1a; 一、基本思想 系统聚类的基本思想是将每个样品&#xff08;或数据点&#xf…

OAK相机的RGB-D彩色相机去畸变做对齐

▌低畸变标准镜头的OAK相机RGB-D对齐的方法 OAK相机内置的RGB-D管道会自动将深度图和RGB图对齐。其思想是将深度图像中的每个像素与彩色图像中对应的相应像素对齐。产生的RGB-D图像可以用于OAK内置的图像识别模型将识别到的2D物体自动映射到三维空间中去&#xff0c;或者产生的…

深入理解Python异常处理机制

在Python编程中&#xff0c;异常处理是一个非常重要的概念。它可以帮助我们捕获程序运行过程中出现的错误&#xff0c;防止程序崩溃&#xff0c;并提供友好的错误信息。本文将详细讲解Python的异常处理机制&#xff0c;并提供丰富的代码示例&#xff0c;帮助您更好地理解和应用…

【Spring MVC】响应结果和设置

​ 我的主页&#xff1a;2的n次方_ 1. 返回静态页面 先创建一个 html 页面 ​ 如果还按照之前的方式进行返回的话&#xff0c;返回的并不是一个 html 页面 RequestMapping("/response") RestController public class ResponseController {RequestMapping(&quo…

React基础使用教程

初识JSX React主要使用的就是jsx语法来编写dom&#xff0c;所以我们要先认识jsx&#xff0c;然后再开始学习两者相结合jsx其实就是在JS中编写HTML的一种写法编写jsx要注意以下几个规则&#xff1a; 定义虚拟DOM时&#xff0c;不要写引号标签中混入JS表达式时要用{}样式的类名指…

2024 Rust现代实用教程:1.3获取rust的库国内源以及windows下的操作

文章目录 一、使用Cargo第三方库1.直接修改Cargo.toml2.使用cargo-edit插件3.设置国内源4.与windows下面的rust不同点 参考 一、使用Cargo第三方库 1.直接修改Cargo.toml rust语言的库&#xff1a;crate 黏贴至Cargo.toml 保存完毕之后&#xff0c;自动下载依赖 拷贝crat…

形态学-闭运算

目录 依赖库显示图像的函数读取图像转换为灰度图像应用二值化阈值处理创建结构元素应用形态学闭运算显示结果 依赖库 首先&#xff0c;我们需要导入必要的库&#xff1a; import cv2 import numpy as npcv2 是OpenCV的Python接口&#xff0c;用于图像处理。numpy 是一个用于科…

在时间敏感网络中启用网络诊断:协议、算法和硬件

英文论文标题&#xff1a;Enabling Network Diagnostics in Time-Sensitive Networking: Protocol, Algorithm, and Hardware 作者信息&#xff1a; Zeyu Wang, Xiaowu He, Xiangwen Zhuge, Shen Xu, Fan Dang, Jingao Xu, Zheng Yang所属机构&#xff1a;清华大学软件学院和…

Pytorch笔记--RuntimeError: NCCL communicator was aborted on rank 3.

1--分布式并行训练&#xff0c;出现以下bug&#xff1a; [E ProcessGroupNCCL.cpp:719] [Rank 3] Watchdog caught collective operation timeout: WorkNCCL(SeqNum1721483, OpTypeALLREDUCE, Timeout(ms)1800000) ran for 1805695 milliseconds before timing out. RuntimeErr…

Docker:安装 Syslog-ng 的技术指南

1、简述 Syslog-ng 是一种流行的日志管理工具&#xff0c;能够集中处理和分析日志。通过 Docker 安装 Syslog-ng 可以简化部署和管理过程。本文将介绍如何使用 Docker 安装 Syslog-ng&#xff0c;并提供一个 Java 示例来展示如何将日志发送到 Syslog-ng。 2、安装 2.1 创建…

[mysql]子查询的概述和分类及单行子查询

子查询引入 查询的基本结构已经给大家了,子查询里面也是有一些新的内容,子查询其实就是在查询中嵌套另一个查询,叫嵌套查询可能大家更容易理解一点..,类似与FOR循环和FOR循环的嵌套,这一章是我们查询的最难的部分,大家 难度是查询的顶峰,多表查询和子查询是非常重要,SQL优化里…