嵌入式设计模式基础--C语言的继承封装与多态
继承,封装和多态是OOP的三大核心特性,它们共同构了面向对象的基础.但嵌入式开发中大量的使用到的却是C语言这种面向过程的语言,那么我们就需要了解如何在C中使用设计模式的思想做功能开发。要了解设计模式,我们就需要先搞清楚 继承,封装和多态在C语言中应该如何体现。
本系列将会使用一个传感器的例子来说明本节内容。
封装
阿光对封装的理解其实就是将对象的属性和方法高度抽象出来,以传感器为例,传感器的属性可以抽象出传感器类型,传感器数据,采样间隔等,方法可以抽象出获取传感器数据的方法以及打印传感器数据的方法等。
有了以上的抽象,我们就可以定义一个基类来表示传感器
typedef struct Sensor Sensor;
struct Sensor {const char* type; // 传感器类型float data; // 传感器数据int samplingInterval; // 采样间隔(单位:毫秒)void (*readData)(Sensor* sensor); // 读取数据的方法void (*printInfo)(Sensor* sensor); // 打印信息的方法
};
创建Sensor对象函数:(基类构造函数)
Sensor* Sensor_create(const char* type, int samplingInterval) {Sensor* sensor = (Sensor*)malloc(sizeof(Sensor));sensor->type = type;sensor->samplingInterval = samplingInterval;sensor->data = 0.0;sensor->readData = Sensor_readData; // 默认读取数据方法sensor->printInfo = Sensor_printInfo; // 默认打印信息方法return sensor;
}
销毁Sensor对象函数:(基类析构函数)
void Sensor_destroy(Sensor* sensor) {free(sensor);
}
以上是对基类的封装,通过封装可以使用基类的方法访问数据,杜绝了直接访问数据的情况,可以有效地做到数据安全和保护。同时封装使得类的内部实现细节对外部透明,那么对于类的属性方法的修改不会影响到外部代码实现,更加方便代码的维护和扩展。同时用户也无需关心传感器数据的内部存储和操作细节,只需通过调用方法即可完成功能。
继承
那么我们假设现在有两款传感器(对象),一款是温度传感器,一款湿度传感器;两个传感器都具有基类的所有属性,但是又会有一些差别,比如温度传感器一般会有最高和对低温的限制,同时对于湿度传感器的话我们可以假定一个适宜的湿度范围为人类的舒适区。那么对于两个对象我们可以分别定义两个派生类:
// 定义一个派生类 TemperatureSensor,用于表示温度传感器
typedef struct TemperatureSensor TemperatureSensor;
struct TemperatureSensor {Sensor sensor; // 继承自 Sensorfloat maxTemp; // 最高温度float minTemp; // 最低温度
};
// 同理,可以定义 HumiditySensor 类来表示湿度传感器
typedef struct HumiditySensor HumiditySensor;
struct HumiditySensor {Sensor sensor; // 继承自 Sensorfloat comfortLevel; // 舒适度
};
那么同样的对于派生类我们需要定义构造和析构函数,以及操作对象的方法。
// 创建 TemperatureSensor 对象的函数
TemperatureSensor* TemperatureSensor_create(int samplingInterval, float maxTemp, float minTemp) // 销毁 TemperatureSensor 对象的函数
void TemperatureSensor_destroy(TemperatureSensor* tempSensor)
// 温度传感器的读取数据方法
void TemperatureSensor_readData(Sensor* sensor)
HumiditySensor* HumiditySensor_create(int samplingInterval, float comfortLevel)
void HumiditySensor_destroy(HumiditySensor* humiditySensor)
void HumiditySensor_readData(Sensor* sensor)
以上便是继承的概念在嵌入式开发中一个例子,不同的传感器对象继承了基类的属性,使得代码具有很好的复用性和扩展性,如果有新增的图像传感器依然可以继承基类的属性且只需要单独定义图像传感器的差异属性,这使得代码各个模块之间相互独立,易于后期维护和扩展。
多态
多态的概念:多态允许对象在继承体系中根据需要动态地表现出不同的行为。通过多态,调用者可以通过一个统一的接口来调用不同对象的具体实现,而无需关心对象的实际类型。
即我们可以通过基类指针调用不同派生类的方法。用到上面的例子中我们就可以这样理解:在一个接口内部,可以通过基类Sensor指针来调用温度和湿度传感器的方法。
int main() {// 创建不同类型的传感器对象Sensor* sensors[2];sensors[0] = (Sensor*)TemperatureSensor_create(1000, 45.0, 15.0);sensors[1] = (Sensor*)HumiditySensor_create(2000, 60.0);// 多态调用,读取数据并打印信息for (int i = 0; i < 2; i++) {sensors[i]->readData(sensors[i]);sensors[i]->printInfo(sensors[i]);}// 销毁对象TemperatureSensor_destroy((TemperatureSensor*)sensors[0]);HumiditySensor_destroy((HumiditySensor*)sensors[1]);return0;
}
以上便是C语言中模拟面向对象中多态的特性,多态使得不同的对象可以使用同一接口实现不同的行为,调用者不需要知道对象的具体类型,只需要知道调用对象的方法即可。做到了各个模块之间解耦。
总结
面向对象的变成模型是设计模式的基础,这种思想将具体的系统分解为独立的对象或类,每个对象负责特定的功能。这种模块化的思想会使得代码的功能更加清晰和易于维护。在后续的简单工厂模式,策略模式等等设计模式中都有很好的体现,这对于嵌入式应用或者驱动开发来说,都是很好的实践。
相关文章:
嵌入式设计模式基础--C语言的继承封装与多态
继承,封装和多态是OOP的三大核心特性,它们共同构了面向对象的基础.但嵌入式开发中大量的使用到的却是C语言这种面向过程的语言,那么我们就需要了解如何在C中使用设计模式的思想做功能开发。要了解设计模式,我们就需要先搞清楚 继承…...
【python爬虫】python+selenium实现Google Play Store应用信息爬虫+apk下载
实验要求:利用pythonselenium实现Google Play Store应用信息爬虫apk下载。 其中: 1、热门应用列表包含200个app,需要点击右侧按钮滑动产生下一页数据,所以需要Selenium来控制页面操作。 2、每个应用的爬虫信息包括:ap…...
RPC协议及库介绍
一.RPC介绍 RPC(Remote Procedure Call),远程过程调用协议,客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样,即允许像调用本地服务一样调用远程服务。 RPC框架的…...
【教程】Docker更换存储位置
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 目录 背景说明 更换教程 1. 停止 Docker 服务 2. 创建新的存储目录 3. 编辑 Docker 配置文件 4. 迁移已有数据到新位置 5. 启动 Docker 服务 6…...
vue3实现JSON格式化和JSONPath提取功能
功能简介 1、JSON数据的格式化 2、通过JSONPath语法对格式化后的数据匹配提取 基础环境参考 vue3flasksqlite前后端项目实战 包安装 npm install jsonpath src/views/JsonFormat.vue <template><div class"json-formatter-container"><el-card cla…...
【springcloud学习(dalston.sr1)】服务消费者通过restTemplate来访问服务提供者(含源代码)(五)
该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) 一般情况下,我们远程调用服务,可以用restTemplate来进行http请求的访问。接…...
在 Angular 中, `if...else if...else`
在 Angular 中,模板语法本身并不直接支持 if...else if...else 这样的多条件分支结构。不过,你可以通过使用 *ngIf 指令结合其else模板功能来实现类似的效果。下面是如何模拟if...else if...else逻辑的方法: 示例:实现if...else …...
深入掌握 Python 切片操作:解锁数据处理的高效密码
在 Python 的编程宇宙中,每一个开发者都在不断探索各种强大且实用的工具,以提升代码的效率与灵活性。其中,切片操作作为 Python 数据处理领域的核心技能之一,就像是一把精巧的瑞士军刀,无论是处理文本信息、分析数据列…...
基于 Kubernetes 部署容器平台kubesphere
一 前言: k8s 大家都已经非常熟悉了,网上流传着非常多的搭建部署文档,有kubeadmin的有二进制的,还有基于第三方的部署工具的,反正是各种部署方法都有,k8s部署技术热门可见一斑。但是不管哪种部署都需要了解…...
lua 作为嵌入式设备的配置语言
从lua的脚本中获取数据 lua中栈的索引 3 | -1 2 | -2 1 | -3 可以在lua的解释器中加入自己自定的一些功能,其实没啥必要,就是为了可以练习下lua...
NVMe简介2
共分2部分,这里是第2部分。 NVMe数据结构 NVMe协议中规定每个提交命令的大小为64字节,完成命令大小为16字节,NVMe命令分为Admin和IO两类,NVMe的数据块组织方式有PRP和SGL两种。提交命令的格式如图5所示。 图5 提交命令数据格 N…...
具身智能梳理以及展望
具身智能相关技术与发展历程 具身智能概念 具身智能指具有自身体验、改变物理世界的智能。 过去 5.4 亿年,地球所有生物智能由身体作用于世界的行为塑造。 1950 年,图灵在《Computing Machinery and Intelligence》论文中首次提出具身智能࿰…...
【Redis实战篇】秒杀优化
1. 秒杀优化-异步秒杀思路 我们来回顾一下下单流程 当用户发起请求,此时会请求nginx,nginx会访问到tomcat,而tomcat中的程序,会进行串行操作,分成如下几个步骤 1、查询优惠卷 2、判断秒杀库存是否足够 3、查询订单…...
【HTTPS基础概念与原理】TLS握手过程详解
以下是 TLS握手过程的详细拆解,涵盖客户端与服务器之间的关键交互步骤,包括ClientHello、ServerHello、证书验证、密钥交换等核心阶段,并对比TLS 1.2与TLS 1.3的差异: 一、TLS握手的核心目标 协商协议版本:确定双方支…...
libmemcached库api接口讲解三
前言:讲解一下如何删除数据 🗑️ libmemcached 删除键操作教程:memcached_delete() / memcached_delete_by_key() 📘 1. 函数作用 用于从 Memcached 中删除指定的 key,包括: memcached_delete()ÿ…...
注解和 XML 两种方式有什么区别?
注解和 XML 是两种常见的配置方式(尤其在 Java 开发中,如 Spring 框架),它们的主要区别体现在配置方式、代码耦合性、可读性、维护性等方面。以下是两者的对比: 1. 配置方式 注解(Annotation) 在…...
[论文阅读]Formalizing and Benchmarking Prompt Injection Attacks and Defenses
Formalizing and Benchmarking Prompt Injection Attacks and Defenses Formalizing and Benchmarking Prompt Injection Attacks and Defenses | USENIX 33rd USENIX Security Symposium (USENIX Security 24) 提出了一个框架来形式化提示注入攻击,对提示注入攻击…...
分布式2(限流算法、分布式一致性算法、Zookeeper )
目录 限流算法 固定窗口计数器(Fixed Window Counter) 滑动窗口计数器(Sliding Window Counter) 漏桶算法(Leaky Bucket) 令牌桶算法(Token Bucket) 令牌桶与漏桶的对比 分布式…...
阿里端到端多模态语音对话开源模型论文速读:Qwen2.5-Omni
Qwen2.5-Omni 技术报告 1. 介绍 Qwen2.5-Omni 技术报告介绍了一个先进的端到端多模态模型 Qwen2.5-Omni,该模型能够感知包括文本、图像、音频和视频在内的多种模态,并能同时以流式方式生成文本和自然语音响应。该模型解决了统一不同理解模态、管理不同…...
React 第四十节 React Router 中 useBeforeUnload的使用详细解析及案例说明
useBeforeUnload 是 React Router 提供的一个自定义钩子,用于在用户尝试关闭页面、刷新页面或导航到外部网站时触发浏览器原生的确认提示。 它的核心用途是防止用户意外离开页面导致数据丢失(例如未保存的表单内容)。 一、useBeforeUnload 核…...
c++STL——哈希表封装:实现高效unordered_map与unordered_set
文章目录 用哈希表封装unordered_map和unordered_set改进底层框架迭代器实现实现思路迭代器框架迭代器重载operator哈希表中获取迭代器位置 哈希表的默认成员函数修改后的哈希表的代码封装至上层容器 用哈希表封装unordered_map和unordered_set 在前面我们已经学过如何实现哈希…...
通过迁移学习改进深度学习模型
在 ArcGIS Living Atlas of the World (Browse | ArcGIS Living Atlas of the World)中,可以下载能够分类或检测影像中要素的预训练深度学习模型。 深度学习模型在与用于训练模型的原始影像十分相似的影像上运行效果最好。 如果您所拥有的影像…...
SpringAI更新:废弃tools方法、正式支持DeepSeek!
AI 技术发展很快,同样 AI 配套的相关技术发展也很快。这不今天刚打开 Spring AI 的官网就发现它又又又又更新了,而这次更新距离上次更新 M7 版本才不过半个月的时间,那这次 Spring AI 给我们带来了哪些惊喜呢?一起来看。 重点升级…...
输入一个正整数,将其各位数字倒序输出(如输入123,输出321)
之前的解法: 这种方法仅支持三位数。 学了while之后,可以利用循环解决。 这种方法动态构建逆序数,支持任意长度的正整数。...
react+html2canvas+jspdf将页面导出pdf
主要使用html2canvasjspdf 1.将前端页面导出为pdf 2.处理导出后图表的截断问题 export default function AIReport() {const handleExport async () > {try {// 需要导出的内容idconst element document.querySelector(#AI-REPORT-CONTAINER);if (!element) {message.err…...
Spring Boot 自动装配技术方案书
Spring Boot 自动装配技术方案书(增强版) 一、Spring Boot 自动装配体系全景解析 1.1 核心设计理念 “约定优于配置”:通过合理的默认配置减少开发工作量“即插即用”:通过标准化扩展机制实现组件自动集成“分层解耦”:业务代码与基础设施分离,通过SPI机制实现扩展二、组…...
面试--HTML
1.src和href的区别 总结来说: <font style"color:rgb(238, 39, 70);background-color:rgb(249, 241, 219);">src</font>用于替换当前元素,指向的资源会嵌入到文档中,例如脚本、图像、框架等。<font style"co…...
(3)python开发经验
文章目录 1 sender返回对象找不到函数2 获取绝对路径3 指定翻译字符 更多精彩内容👉内容导航 👈👉Qt开发 👈👉python开发 👈 1 sender返回对象找不到函数 在PySide6中多个信号绑定一个槽函数,使…...
机密虚拟机的威胁模型
本文将介绍近年兴起的机密虚拟机(Confidential Virtual Machine)技术所旨在抵御的威胁模型,主要关注内存机密性(confidentiality)和内存完整性(integrity)两个方面。在解释该威胁可能造成的问题…...
LLM笔记(一)基本概念
LLMs from scratch Developing an LLM: Building, Training, Finetuning LLM 的基本概念与定义: LLM是深度神经网络模型,能够理解、生成和解释类似人类的语言。“大型”指的是模型参数数量巨大以及训练数据集的规模庞大。LLM通常基于Transformer架构,并通…...
嵌入式(c语言篇)Day9
嵌入式Day9 C语言字符串标准库函数笔记 一、概述 C语言提供了一系列字符串标准库函数用于处理字符串,使用这些函数需要包含头文件 <string.h>。主要函数包括求字符串长度、字符串复制、字符串拼接和字符串比较等。我们不仅要理解这些函数的行为,…...
006-nlohmann/json 结构转换-C++开源库108杰
绝大多数情况下,程序和外部交换的数据,都是结构化的数据。 1. 手工实现——必须掌握的基本功 在的业务类型的同一名字空间下,实现 from_json 和 to_json 两个自由函数(必要时,也可定义为类型的友元函数)&a…...
b站视频如何下载到电脑——Best Video下载器
你是不是也经常在B站刷到超赞的视频,想保存到电脑慢慢看,却发现下载不了?别急,今天教你一个超简单的方法,轻松下载B站视频到电脑,高清画质,随时随地想看就看! 为什么需要下载B站视频…...
【行为型之模板方法模式】游戏开发实战——Unity标准化流程与可扩展架构的核心实现
文章目录 🧩 模板方法模式(Template Method Pattern)深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码(关卡流程系统)1. 定义抽象模板类2. 实现具体子类3. 客户端使用 四、模式进阶技巧1. 钩子方法&am…...
每日算法-250514
每日算法学习记录 (2024-05-14) 今天记录三道 LeetCode 算法题的解题思路和代码。 1. 两数之和 题目截图: 解题思路 这道题要求我们从一个整数数组中找出两个数,使它们的和等于一个给定的目标值 target,并返回这两个数的下标。 核心思路是使用 哈希…...
信息安全入门基础知识
信息安全是保护信息系统和数据免受未经授权的访问、使用、披露、中断、修改或破坏的实践。对于个人和组织来说,了解信息安全的基础知识至关重要。 1. CIA三元组 信息安全的三个主要目标,也称为CIA三元组: 机密性(Confidentiality): 确保信息不被未经授权的人访问或披露完整性…...
力扣-98.验证二叉搜索树
题目描述 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 class Solutio…...
Java 框架配置自动化:告别冗长的 XML 与 YAML 文件
在 Java 开发领域,框架的使用极大地提升了开发效率和系统的稳定性。然而,传统框架配置中冗长的 XML 与 YAML 文件,却成为开发者的一大困扰。这些配置文件不仅书写繁琐,容易出现语法错误,而且在项目规模扩大时ÿ…...
大疆无人机自主飞行解决方案局限性及增强解决方案-AIBOX:特色行业无人机巡检解决方案
大疆无人机自主飞行解决方案局限性及增强解决方案-AIBOX:特色行业无人机巡检解决方案 大疆无人机是低空行业无人机最具性价比的产品,尤其是大疆机场3的推出,以及持续自身产品升级迭代,包括司空2、大疆智图以及大疆智运等专业软件和…...
【机器人】复现 SG-Nav 具身导航 | 零样本对象导航的 在线3D场景图提示
SG-Nav提出了一种新的零样本物体导航框架,用三维场景图来表示观察到的场景。 并设计了一个分层的思路链提示,帮助LLM通过遍历节点和边,根据场景上下文推理目标位置。 本文分享SG-Nav复现和模型推理的过程~ 下面是一个查找椅子示…...
详细说说Spring的IOC机制
Spring 的 IOC(控制反转)是框架的核心机制,用于管理对象的创建和依赖注入,通过将控制权从应用程序代码转移到容器,实现组件间的解耦。以下是详细解析: 1. IOC 核心概念 控制反转(Inversion of C…...
Android Activity之间跳转的原理
一、Activity跳转核心流程 Android Activity跳转的底层实现涉及 系统服务交互、进程间通信(IPC) 和 生命周期管理,主要流程如下: startActivity() 触发请求 应用调用 startActivity() 时,通过 Inst…...
第二个五年计划!
下一阶段!5年后!33岁!体重维持在125斤内!腰围74! 健康目标: 体检指标正常,结节保持较小甚至变小! 工作目标: 每年至少在一次考评里拿A(最高S,A我理…...
交易所功能设计的核心架构与创新实践
交易所功能设计的核心架构与创新实践 ——从用户体验到安全合规的全维度解析 一、核心功能模块:构建交易生态的四大支柱 1. 用户账户管理 多因子身份验证:集成邮箱/手机注册、谷歌验证器(2FA)、活体检测(误识率<0…...
Windows10安装WSA
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、WSAOnWin10二、安装1.第一种方法2.第二种方法 总结 前言 有时候工作需要用到WSA,然而我们的电脑是Windows10的不能直接安装。接下来我就教你们…...
标签部件(lv_label)
一、如何创建标签部件以及设置文本? 知识点1:如何创建标签部件 lv_obj_t *label lv_label_create(parent); 知识点2:设置文本的3种方式 ①直接设置文本,存储文本的内存动态分配:lv_label_set_text(label,"he…...
Spring中的循环引用
循环依赖发生在两个或两个以上的bean互相持有对方,形成闭环。Spring框架允许循环依赖存在,并通过三级缓存解决大部分循环依赖问题: 一级缓存:单例池,缓存已完成初始化的bean对象。 二级缓存:缓存尚未完成生…...
技术选型不当,如何避免影响项目进展
建立选型评估机制、综合考虑业务与技术匹配度、引入技术决策审查流程、做好选型后的风险预案与替代方案准备 是避免因技术选型不当影响项目进展的关键措施。尤其要重视建立选型评估机制,通过全流程、数据化、多维度的评估体系,确保所选技术能在性能、可维…...
图表制作-基础饼图
首先登录自己的账号,没有账号的可以注册一个。 登录之后,在左侧菜单栏找到图表制作-统计图。 点击新建统计图,点击饼图-基础饼图。 初始会有一些演示数据,可以根据自己的需要进行修改。 如果嫌手动修改太麻烦,可以导入…...
Java 大视界 -- 基于 Java 的大数据分布式存储在工业互联网海量设备数据长期存储中的应用优化(248)
往期文章推荐: 《大数据新视界》和《 Java 大视界》专栏: Java 大视界 – Java 大数据在智能教育自适应学习路径动态调整中的应用与实践(247)(最新)Java 大视界 – Java 大数据在智能安防生物特征识别系统中的多模态…...