天天看點

c語言struct_面向對象設計思想-C語言

面向對象的三個特征:封裝,繼承,多态。但是C語言不是面向對象程式設計語言,是以需要借助一些技巧來實作這三個特征:(1)C語言沒有成員函數,struct隻能封裝資料,不能封裝方法,可以在struct裡使用函數指針;(2)C語言不支援繼承,可以在一個struct裡包含另一個struct;(3)C語言也沒有虛函數,實作多态就更麻煩了,我不會。舉個例子:現在有Point結構體定義如下

struct Point{  float x;  float y;};
           

如果想從Point派生出Circle,可以這麼寫:

struct Circle{  struct Point o; //圓心  float r;        //半徑};struct Circle C;struct Point *pPoint = (struct Point*)(&C);
           

此時如果将Circle類型的指針強制轉換成Point類型指針,因為記憶體是順序連續的,是以沒問題,pPoint->x通路的是C.o.x,pPoint->y通路的是C.o.y.也就是說在需要基類指針的地方可以傳入派生類的指針。

但是如果将o和r的順序換一下就錯了。

struct Circle{  float r;        //半徑  struct Point o; //圓心};struct Circle C;struct Point *pPoint = (struct Point*)(&C);//這麼轉會出問題
           

簡單來說就是如果想使用C語言的繼承,那麼基類對象一定要寫在派生類的最前面!但是對C語言程式設計而言,不建議使用繼承和多态,使用封裝就可以了。對封裝的了解可以退化為:不直接通路結構體的成員變量而是通過函數去通路(C語言沒有private屬性,直接通路成員變量總是可以的,但是不建議這麼做);此外C語言結構體沒有this指針,是以使用函數指針封裝方法也用的比較少,更多的是提供一些全局函數,将結構體指針作為參數傳進去操作。

假設有個Moubus資料包的結構體:

#define PACK_SIZE 256struct ModbusPack{  uint8_t data[PACK_SIZE];  uint8_t len;};
           

還有和它對應的操作函數:

void Modbus_init(struct ModbusPack *pThis);void Modbus_append(struct ModbusPack *pThis,uint8_t v);void Modbus_appends(struct ModbusPack *pThis,uint8_t *vs,uint8_t len);uint8_t Modbus_len(struct ModbusPack *pThis);void Modbus_append_crc(struct ModbusPack *pThis);uint8_t Modbus_check(struct ModbusPack *pThis);void Modbus_init_query(struct ModbusPack *pThis,uint8_t addr,uint8_t fc,uint16_t regBase,uint16_t regNum);void Modbus_print(struct ModbusPack *pThis);
           

對于Modbus_len這個函數的實作如下:

uint8_t Modbus_len(struct ModbusPack *pThis) {  //省略對指針是否為空的判斷  return pThis->len;}
           

看起來比直接通路成員變量複雜,好處在于當修改了ModbusPack的實作,将len改為m_len,則隻需要修改Modbus_xxx函數就行了,不影響其他地方對這個函數的調用,因為調用的地方隻依賴于這個函數的名字,而不需要知道相應結構體的具體實作。

struct ModbusPack{  uint8_t m_data[PACK_SIZE];  uint8_t m_len;};uint8_t Modbus_len(struct ModbusPack *pThis) {  //省略對指針是否為空的判斷  return pThis->m_len;}
           

簡單的使用例子如下:

#include "modbus.h"int main(){  struct ModbusPack pack;  Modbus_init(&pack);//C語言沒有構造函數,通過初始化函數初始化對象  Modbus_init_query(&pack,0x01,0x03,0x0000,0x0002);  Modbus_print(&pack);  return 0;}
           

運作結果:

c語言struct_面向對象設計思想-C語言

友情提示:找對象雖易,面向對象不易,且行且珍惜。