ToB企服应用市场:ToB评测及商务社交产业平台

标题: c语言实现this指针效果 [打印本页]

作者: 惊落一身雪    时间: 2024-1-24 15:17
标题: c语言实现this指针效果
概要

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

现有方案

对象就是具有属性与方法的集合体,以LED举例,它的属性就是端口,引脚,亮使能标志等,方法就是亮,灭。
了解到现有的c语言面向对象实现方法都需要手动传入对象的引用,如下这种方式:
  1. typedef struct _LED_TYPEDEF{
  2.         //属性
  3.         struct _Privated_Attr{
  4.                 GPIO_InitTypeDef GPIO_Body;
  5.                 GPIO_TypeDef *GPIOx;
  6.                 GPIO_PinState ENbit;
  7.         } Privated_Attr;
  8.        
  9.         //方法
  10.         void (*LightUp)(struct _LED_TYPEDEF *);
  11.         void (*LightOff)(struct _LED_TYPEDEF *);
  12. }LED_TypeDef;
复制代码
上面的结构体中有一个嵌入的结构体变量,主要用途就是类似私有变量,类外不可直接访问的目的,也是出于属性只由方法操作,这样可以对属性值的合理性做出一定限制与约束,然后方法的参数必须加入对象的引用,也就是传入对象地址。
此时调用方法为:
  1. //实例化对象
  2. LED_TypeDef BSP_LED1;
  3. LED_TypeDef BSP_LED2;
  4. //对象方法使用
  5. BSP_LED1.LightUp(&BSP_LED1); //led1亮
  6. BSP_LED2.LightOff(&BSP_LED2);//led2灭
复制代码
这种方式比较麻烦,所以有必要引入c++的this指针方式。
this方案

目的:为了简写对象方法的调用模式。
所谓的this指针可以简单理解为编译器帮我们把对象引用传递到方法中了。
单一bsp方案

此单一bsp意为板子上只有这一个外设,所以这个bsp对象只需要一个this指针,以uart举例
  1. typedef struct _UART_OBJ_TYPEDEF{
  2.         //属性
  3.         struct _PrivateAttr{
  4.                 uint16_t Buf_Cnt;
  5.                 UART_HandleTypeDef UARTxHandler;               
  6.         }PrivateAttr;
  7.         uint8_t Is_RX_OV;
  8.         uint8_t Is_RX_OK;
  9.         uint8_t RX_Buf[UART_RX_MAX_SIZE];
  10.        
  11.         //方法
  12.         void (*SendChar)(struct _UART_OBJ_TYPEDEF *,uint8_t chr);
  13.         void (*SendStr)(struct _UART_OBJ_TYPEDEF *,uint8_t *str);
  14.         void (*ClearBuf)(void);
  15.         void (*ClearFlag)(void);
  16.         void (*BufAppend)(uint8_t byte);
  17.         uint16_t (*GetBufLength)(void);
  18. }UART_Obj_TypeDef;
复制代码
可以看到方法中不再需要手动传入对象引用了。
  1. UART_Obj_TypeDef UART_Debug_Obj; //实例化对象
  2. static UART_Obj_TypeDef *mthis = &UART_Debug_Obj; //this指针实现对象引用
复制代码
这样就利用static文件的作用域实现为每个bsp对象实现一个this指针效果。
  1. //将数据放入缓冲区
  2. UART_Debug_Obj.BufAppend(res);
  3. //清空缓冲区
  4. UART_Debug_Obj.ClearBuf();
复制代码
多个同类bsp方案
  1. //bsp对象的this数组偏移量
  2. #define BSP_LED1_OFFSET 0
  3. #define BSP_LED2_OFFSET 1
  4. //间接改变this的指向
  5. #define BSP_LED1        (this_ledx = BSP_LED1_OFFSET);_BSP_LED1
  6. #define BSP_LED2        (this_ledx = BSP_LED2_OFFSET);_BSP_LED2
  7. struct _LED_TYPEDEF;
  8. typedef struct _LED_TYPEDEF{
  9.         struct _Privated_Attr{
  10.                 GPIO_InitTypeDef GPIO_Body;
  11.                 GPIO_TypeDef *GPIOx;
  12.                 GPIO_PinState ENbit;
  13.         } Privated_Attr;
  14.         void (*LightUp)(void);
  15.         void (*LightOff)(void);
  16. }LED_TypeDef;
复制代码
使用宏定义的方式间接改变this的指向
  1. //实例化2个同类对象
  2. LED_TypeDef _BSP_LED1;
  3. LED_TypeDef _BSP_LED2;
  4. //this指针与this数组
  5. static LED_TypeDef* This_Arr[LED_NUM] = {&_BSP_LED1,&_BSP_LED2};
  6. static LED_TypeDef* mthis;
  7. //this指向偏移量(因为外面要用,所以名字不要冲突,最好和bsp对象相关)
  8. uint8_t this_ledx = BSP_LED1_OFFSET;
复制代码
  1. //方法定义
  2. void LightUp(){
  3.         mthis = This_Arr[this_ledx]; //通过this指针偏移来确定使用哪个对象
  4.         HAL_GPIO_WritePin(mthis->Privated_Attr.GPIOx,\
  5.         mthis->Privated_Attr.GPIO_Body.Pin,\
  6.         mthis->Privated_Attr.ENbit);
  7. }
复制代码
总结

基于面向对象的思想对于代码的结构和可读性上都有一定的利处,特别在裸机编写过程中,由于不受系统的干预,对于思路与框架的设计都清晰起来,目前还在不断改善中,这种方式的缺陷也很明显,只适用在静态的情况,要想动态实现只有编译器能操作了,但还是希望这种方式可以很好的在项目中使用。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4