概要

由于目前在做一个比较复杂的嵌入式项目,想要借此提升一下代码的结构设计能力,所以想要以面向对象的思想来完成这个项目,即把每个板载外设资源视为一个对象,采用msp+bsp的模式,对每个bsp外设实现对象化处理,现有方案需要手动传入对象引用,调用方法时比较麻烦,所以考虑简化调用方式。

面向对象实现思路

现有方案

对象就是具有属性与方法的集合体,以LED举例,它的属性就是端口,引脚,亮使能标志等,方法就是亮,灭。

了解到现有的c语言面向对象实现方法都需要手动传入对象的引用,如下这种方式:

typedef struct _LED_TYPEDEF{
//属性
struct _Privated_Attr{
GPIO_InitTypeDef GPIO_Body;
GPIO_TypeDef *GPIOx;
GPIO_PinState ENbit;
} Privated_Attr; //方法
void (*LightUp)(struct _LED_TYPEDEF *);
void (*LightOff)(struct _LED_TYPEDEF *);
}LED_TypeDef;

上面的结构体中有一个嵌入的结构体变量,主要用途就是类似私有变量,类外不可直接访问的目的,也是出于属性只由方法操作,这样可以对属性值的合理性做出一定限制与约束,然后方法的参数必须加入对象的引用,也就是传入对象地址。

此时调用方法为:

//实例化对象
LED_TypeDef BSP_LED1;
LED_TypeDef BSP_LED2; //对象方法使用
BSP_LED1.LightUp(&BSP_LED1); //led1亮
BSP_LED2.LightOff(&BSP_LED2);//led2灭

这种方式比较麻烦,所以有必要引入c++的this指针方式。

this方案

目的:为了简写对象方法的调用模式。

所谓的this指针可以简单理解为编译器帮我们把对象引用传递到方法中了。

单一bsp方案

此单一bsp意为板子上只有这一个外设,所以这个bsp对象只需要一个this指针,以uart举例

typedef struct _UART_OBJ_TYPEDEF{
//属性
struct _PrivateAttr{
uint16_t Buf_Cnt;
UART_HandleTypeDef UARTxHandler;
}PrivateAttr;
uint8_t Is_RX_OV;
uint8_t Is_RX_OK;
uint8_t RX_Buf[UART_RX_MAX_SIZE]; //方法
void (*SendChar)(struct _UART_OBJ_TYPEDEF *,uint8_t chr);
void (*SendStr)(struct _UART_OBJ_TYPEDEF *,uint8_t *str);
void (*ClearBuf)(void);
void (*ClearFlag)(void);
void (*BufAppend)(uint8_t byte);
uint16_t (*GetBufLength)(void);
}UART_Obj_TypeDef;

可以看到方法中不再需要手动传入对象引用了。

UART_Obj_TypeDef UART_Debug_Obj; //实例化对象
static UART_Obj_TypeDef *mthis = &UART_Debug_Obj; //this指针实现对象引用

这样就利用static文件的作用域实现为每个bsp对象实现一个this指针效果。

//将数据放入缓冲区
UART_Debug_Obj.BufAppend(res);
//清空缓冲区
UART_Debug_Obj.ClearBuf();

多个同类bsp方案

//bsp对象的this数组偏移量
#define BSP_LED1_OFFSET 0
#define BSP_LED2_OFFSET 1 //间接改变this的指向
#define BSP_LED1 (this_ledx = BSP_LED1_OFFSET);_BSP_LED1
#define BSP_LED2 (this_ledx = BSP_LED2_OFFSET);_BSP_LED2 struct _LED_TYPEDEF; typedef struct _LED_TYPEDEF{
struct _Privated_Attr{
GPIO_InitTypeDef GPIO_Body;
GPIO_TypeDef *GPIOx;
GPIO_PinState ENbit;
} Privated_Attr;
void (*LightUp)(void);
void (*LightOff)(void);
}LED_TypeDef;

使用宏定义的方式间接改变this的指向

//实例化2个同类对象
LED_TypeDef _BSP_LED1;
LED_TypeDef _BSP_LED2;
//this指针与this数组
static LED_TypeDef* This_Arr[LED_NUM] = {&_BSP_LED1,&_BSP_LED2};
static LED_TypeDef* mthis;
//this指向偏移量(因为外面要用,所以名字不要冲突,最好和bsp对象相关)
uint8_t this_ledx = BSP_LED1_OFFSET;
//方法定义
void LightUp(){
mthis = This_Arr[this_ledx]; //通过this指针偏移来确定使用哪个对象
HAL_GPIO_WritePin(mthis->Privated_Attr.GPIOx,\
mthis->Privated_Attr.GPIO_Body.Pin,\
mthis->Privated_Attr.ENbit);
}

总结

基于面向对象的思想对于代码的结构和可读性上都有一定的利处,特别在裸机编写过程中,由于不受系统的干预,对于思路与框架的设计都清晰起来,目前还在不断改善中,希望这种方式可以很好的在项目中使用。

c语言实现this指针效果的更多相关文章

  1. C语言之漫谈指针(下)

    C语言之漫谈指针(下) 在上节我们讲到了一些关于指针的基础知识: 详见:C语言之漫谈指针(上) 本节大纲: 零.小tips 一.字符指针 二.指针数组与数组指针 三.数组传参与指针传参 四.函数指针及 ...

  2. Swift3.0语言教程使用指针创建和初始化字符串

    Swift3.0语言教程使用指针创建和初始化字符串 Swift3.0语言教程使用指针创建和初始化字符串苹果的Swift团队花了不少功夫来支持C的一些基础特性.C语言中为我们提供了指针,Swift也不例 ...

  3. C语言中的指针数组

    C语言中的指针数组是什么,像 char *a[]={"ddd","dsidd","lll"}; 这里讲一下注意如果我们使用了a也就是首元素的 ...

  4. 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化

    C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...

  5. GO语言中的指针

    http://www.tizgrape.com/?p=100 Go语言中的指针语法和C++一脉相承,都是用*作为符号,虽然语法上接近,但是实际差异不小. Go使用var定义变量: var v6 *in ...

  6. 由链表初始化看C语言的二级指针

    先来看C语言创建链表.插入节点和遍历链表的一段代码: #include <stdio.h> #include <stdlib.h> typedef int ElemType; ...

  7. C语言 > 数组和指针

    C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...

  8. EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象

    EF+LINQ事物处理   在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...

  9. C语言结构体指针的引用问题

    在写栈的一个应用时遇见这样的一个问题 SqStack s; s->base = (int*)malloc(sizeof(int)*10); 通过这样一个代码引用的时候,会导致程序出现异常 经过一 ...

  10. Go语言基础之指针

    区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针. 要搞明白Go语言中的指针需要先知道3个概念:指针地址.指针类型和指针取值. Go语言中的指针 Go语言中的函数传参都是值拷贝 ...

随机推荐

  1. 2023HWS_RE复现

    2023HWS_RE复现 参考wp:https://oacia.cc/hws-2023/ Android 参考这篇文章:https://www.52pojie.cn/thread-1680984-1- ...

  2. AI绘画工具MJ新功能有点东西,小白也能轻松一键换装

    先看最终做出来的效果 直接来干货吧.Midjourney,下面简称MJ 1.局部重绘功能来袭 就在前两天,MJ悄咪咪上线了这个被众人期待的新功能:局部重绘. 对于那些追求创新和个性化的设计师来说,局部 ...

  3. 拯救“消失的她”——双系统grub完美恢复方案

    双系统grub意外消失怎么办? 不用重装系统.不用去维修店.不会丢数据,教你一招,完美恢复grub! 背景 我的电脑是windows和linux双系统,启动项使用的grub.某天准备切换linux时突 ...

  4. C#结合OpenCVSharp4图片相似度识别

    OpenCVSharp4图片相似度识别 需求背景:需要计算两个图片的相似度,然后将相似的图片进行归纳 1. 图片相似度算法 由于我是CRUD后端仔,对图像处理没什么概念.因此网上调研了几种相似度算法分 ...

  5. 【题解】Educational Codeforces Round 142(CF1792)

    没有手速,再加上被 E 卡了,废掉了. A.GamingForces 题目描述: Monocarp 正在玩电脑游戏.他打算杀死 \(n\) 个怪兽,第 \(i\) 个的血量为 \(h_i\). Mon ...

  6. 分拣平台API安全治理实战 | 京东物流技术团队

    导读 本文主要基于京东物流的分拣业务平台在生产环境遇到的一些安全类问题,进行定位并采取合适的解决方案进行安全治理,引出对行业内不同业务领域.不同类型系统的安全治理方案的探究,最后笔者也基于自己在金融领 ...

  7. VOLTE:MIUI14无5G信号、通话质量差、短信收不到的原因之一

    在最近一次miui版本更新后的一段时间里,先后出现以下一些情况: 1. 在"双卡与移动网络"设置中,无论如何折腾"5G网络"开关或者"5G网络模式选择 ...

  8. 7.4 通过API枚举进程权限

    GetTokenInformation 用于检索进程或线程的令牌(Token)信息.Token是一个数据结构,其包含有关进程或线程的安全上下文,代表当前用户或服务的安全标识符和权限信息.GetToke ...

  9. 前端三件套系例之BootStrap——BootStrap基础、 BootStrap布局

    文章目录 1 BootStrap基础 1 什么是BootStrap 2 BootStrap的版本 3 BootStrap 下载 4 CDN服务 5 目录结构 6 基本模板 7 浏览器支持 8 浏览器兼 ...

  10. idea2020.3 安装插件JetBrains 插件市场安装 Cloud Toolkit

    <Cloud Toolkit User Guide> 本文是 Alibaba Cloud Toolkit 的使用文档指引,所有相关的使用参考,都可以在本文中找到.如果在使用中有任何问题,请 ...