c語言實現this指針效果
概要
由于目前在做一個比較復雜的嵌入式項目,想要借此提升一下代碼的結構設計能力,所以想要以面向對象的思想來完成這個項目,即把每個板載外設資源視為一個對象,采用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方案,有一個最大的缺點,只要涉及到多線程,或是中斷,就是會有線程安全的風險,因為使用的偏移變量是全局變量。
//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);
}
總結
基于面向對象的思想對于代碼的結構和可讀性上都有一定的利處,特別在裸機編寫過程中,由于不受系統的干預,對于思路與框架的設計都清晰起來,目前還在不斷改善中,這種方式的缺陷也很明顯,只適用在靜態的情況,要想動態實現只有編譯器能操作了,但還是希望這種方式可以很好的在項目中使用。
本文來自博客園,作者:pie_thn,轉載請注明原文鏈接:http://www.rzrgm.cn/pie-o/p/17874200.html

浙公網安備 33010602011771號