当前位置: 首页 > news >正文

C 语言面向对象风格封装的经典技巧(STM32F1 标准库实现)

“把函数装进结构体,把结构体装进函数”是 C 语言中实现面向对象风格封装的经典技巧。它通过结构体容纳函数指针(模拟“方法”),再通过一个工厂函数返回该结构体的实例(模拟“对象”),从而将数据与操作绑定,并隐藏具体实现。更换硬件时只需修改工厂函数内部的函数指针绑定,调用方代码完全不变。

一、核心思想

  1. 函数装进结构体
    定义一个结构体,其中包含多个函数指针成员,这些指针指向与该模块相关的操作函数(如initonofftoggle)。这相当于定义了一个“接口”或“虚表”。

  2. 结构体装进函数
    编写一个初始化/工厂函数,在该函数内部:

    • 定义该结构体类型的局部变量。
    • 将函数指针指向具体的硬件操作函数(这些函数可以是static的,对外不可见)。
    • 返回该结构体(或返回其指针),调用方通过这个结构体来调用操作。
  3. 效果
    调用方只看到结构体中的函数指针,不知道底层是 GPIO、PWM 还是其他硬件。更换硬件时,只需修改工厂函数内部的函数指针映射,无需修改任何调用代码。

二、示例:可更换硬件的 LED 模块

下面以 LED 控制为例,展示如何将LED_On,LED_Off,LED_Toggle封装进结构体,再通过一个函数返回该结构体。

1. 定义接口结构体(放在头文件中)

// led_interface.h#ifndef__LED_INTERFACE_H#define__LED_INTERFACE_Htypedefstruct{void(*init)(void);void(*on)(void);void(*off)(void);void(*toggle)(void);}LED_Ops;// 工厂函数:返回封装了具体操作的 LED_Ops 结构体LED_OpsLED_Create(void);#endif

2. 实现具体硬件操作(隐藏在 .c 文件中)

// led_stm32.c (使用 STM32 标准库)#include"led_interface.h"#include"stm32f10x.h"// 具体硬件配置(更换硬件时只改这里)#defineLED_PORTGPIOB#defineLED_PINGPIO_Pin_5#defineLED_PORT_CLKRCC_APB2Periph_GPIOB#defineLED_ON_LEVELBit_RESET// 低电平点亮#defineLED_OFF_LEVELBit_SET/* 前向声明所有静态函数 */staticvoidhw_init(void);staticvoidhw_on(void);staticvoidhw_off(void);staticvoidhw_toggle(void);// 内部实现函数(static,对外不可见)staticvoidhw_init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(LED_PORT_CLK,ENABLE);GPIO_InitStructure.GPIO_Pin=LED_PIN;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(LED_PORT,&GPIO_InitStructure);hw_off();// 初始熄灭}staticvoidhw_on(void){GPIO_WriteBit(LED_PORT,LED_PIN,LED_ON_LEVEL);}staticvoidhw_off(void){GPIO_WriteBit(LED_PORT,LED_PIN,LED_OFF_LEVEL);}staticvoidhw_toggle(void){GPIO_WriteBit(LED_PORT,LED_PIN,(BitAction)(1-GPIO_ReadOutputDataBit(LED_PORT,LED_PIN)));}// 工厂函数实现:将具体函数指针装入结构体并返回LED_OpsLED_Create(void){LED_Ops ops;ops.init=hw_init;ops.on=hw_on;ops.off=hw_off;ops.toggle=hw_toggle;returnops;}

3. 调用方代码(完全与硬件无关)

// main.c#include"led_interface.h"intmain(void){LED_Ops led=LED_Create();// 创建对象,内部已绑定具体硬件操作led.init();// 初始化硬件while(1){led.on();delay(500000);led.off();delay(500000);// led.toggle();}}

三、更换硬件时如何修改?

假设要将 LED 换到GPIOC, Pin 13,且改为高电平点亮

只需修改led_stm32.c中的宏定义和hw_on/hw_off的实现逻辑:

#defineLED_PORTGPIOC#defineLED_PINGPIO_Pin_13#defineLED_PORT_CLKRCC_APB2Periph_GPIOC#defineLED_ON_LEVELBit_SET// 高电平点亮#defineLED_OFF_LEVELBit_RESETstaticvoidhw_on(void){GPIO_WriteBit(LED_PORT,LED_PIN,LED_ON_LEVEL);}staticvoidhw_off(void){GPIO_WriteBit(LED_PORT,LED_PIN,LED_OFF_LEVEL);}// hw_toggle 会自动适应,因为内部读取当前电平再翻转

main.cled_interface.h完全不需要改动。如果换成其他平台(如 Arduino、Linux GPIO),只需重写hw_xxx函数,工厂函数内部的绑定随之改变,上层代码依然不变。

四、进阶:使用指针返回结构体(避免拷贝)

如果结构体较大,可以返回指针:

// 头文件LED_Ops*LED_Create(void);// 实现文件staticLED_Ops ops;// 静态实例LED_Ops*LED_Create(void){ops.init=hw_init;ops.on=hw_on;ops.off=hw_off;ops.toggle=hw_toggle;return&ops;}// 调用LED_Ops*led=LED_Create();led->init();led->on();

五、总结

技巧作用示例
函数装进结构体定义统一接口,模拟类的成员函数LED_Ops包含onoff等函数指针
结构体装进函数工厂模式,封装具体实现,隐藏硬件差异LED_Create()返回绑定好具体hw_xxx的结构体

这种封装方式在嵌入式、驱动开发、库设计中非常常见(如 Linux 内核的file_operations、RT-Thread 的设备驱动框架)。它实现了接口与实现分离,更换底层硬件时只需修改一个源文件,真正做到了“更换硬件时仅需修改一处代码”。

http://www.jsqmd.com/news/639037/

相关文章:

  • 如何快速掌握Audiveris:免费开源乐谱识别工具终极指南
  • 深聊靠谱的通过式抛丸机厂家怎么选,铜材用设备优质之选 - mypinpai
  • 如何安全备份微信聊天记录:完整导出实战指南
  • (三)PointPillars在MMDetection3D中的数据处理流程深度剖析——从原始点云到训练样本
  • 本地千万级图片搜索工具终极指南:快速找回相似图片的完整解决方案
  • 2026年知名的抗倍特板隔断/A级阻燃HPL抗倍特板/松田抗倍特板/抗倍特板HPL防水防潮板厂家选购指南与推荐 - 行业平台推荐
  • 基于深度学习的红外目标检测系统 yolo11红外小目标检测+红外无人机视角行人识别+车辆检测
  • 《舌尖上的中国》看一口艾饼,满是春天的味道
  • R3nzSkin实战指南:英雄联盟内存换肤技术深度解析与安全部署方案
  • 有实力的养发品牌加盟哪家好,盘点行业口碑出众的加盟项目 - myqiye
  • RK3588 Linux下Camera偏色与光线问题的3A调试指南
  • 3种安卓位置模拟方案深度对比:FakeLocation技术实现与应用指南
  • 5分钟上手MinerU API:实现学术论文截图的内容总结与图表分析
  • 2026年全国羊奶粉品牌综合测评报告:国产金奖品牌美力源乳业领跑 - 深度智识库
  • 2026 Temu广告投放优化三大策略,让广告投放更高效! - 跨境小媛
  • 本地项目云服务器部署
  • nli-distilroberta-base安全与隐私考量:模型部署中的风险与缓解措施
  • 别再只写data()了!深入理解PyQt5 QAbstractItemModel中flags()和setData()的实战用法
  • YaeAchievement:3分钟搞定原神成就导出的终极解决方案
  • Rust的闭包语法分析
  • 小红书场景化内容杀招:把“卖产品”变成“卖生活“,本地商家高收藏笔记模板 - Redbook_CD
  • Mythos、OpenClaw、GLM-5.1 连续出现后,Agent 系统的测试边界开始重写
  • CUDA环境权限问题解析:从mmcv-full安装报错Permission denied到系统级解决方案
  • Adobe-GenP:轻松激活Adobe Creative Cloud的完整解决方案
  • SDXL 1.0电影级绘图工坊效果展示:同一提示词下5种预设风格生成效果全景对比
  • 视频封面批量制作工具完整使用指南:从素材准备到批量输出的操作全流程
  • React Fiber 调度优先级优化方案
  • 吉林省快到家家政服务有限公司简介与业务介绍 - 深圳昊客网络
  • 武汉佰利和建筑防水工程有限公司:东西湖区防水维修价格 - LYL仔仔
  • 从四个 Gateway 插件到 SAP_GWFND,读懂 AS ABAP 7.40 到 7.50 的架构转身