加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

嵌入式 C 語言面向?qū)ο缶幊?--- 封裝

07/08 10:05
380
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師,關(guān)注我,一起變得更加優(yōu)秀!

大部分使用 C 語言進(jìn)行開發(fā)的工程師,在接觸更高級(jí)的編程語言之前,都認(rèn)為 C 語言是面向過程的。

事實(shí)也是如此,對于一些小規(guī)模的單片機(jī)應(yīng)用程序,一般都是使用“面向過程”的思維進(jìn)行單片機(jī)C語言編程開發(fā)。

但是,如果是需要用C語言開發(fā)一些規(guī)模比較大的軟件的時(shí)候,比如操作系統(tǒng)內(nèi)核,文件系統(tǒng)底層,數(shù)據(jù)庫底層,等等,這個(gè)時(shí)候,就需要用面向?qū)ο蟮乃枷肴タ紤]和設(shè)計(jì)整個(gè)軟件框架了。

嵌入式Linux的內(nèi)核,雖然是使用 C 語言編寫的,但里面的設(shè)計(jì)大部分都使用了面向?qū)ο蟮木幊趟枷搿?/p>

很多單片機(jī)工程師或者嵌入式Linux驅(qū)動(dòng)初學(xué)者,有時(shí)候會(huì)覺得驅(qū)動(dòng)入門特別困難,很大一部分原因是,他們會(huì)用“過程式思維”去嘗試學(xué)習(xí)驅(qū)動(dòng)框架和內(nèi)核框架,而非從“整體對象”的思維方向出發(fā),這樣容易導(dǎo)致水土不服。

任何編程語言只是一種工具,而編程思想是指導(dǎo)我們用好這個(gè)工具的關(guān)鍵。

C 語言只是工具,而面向?qū)ο笫且环N編程思想,用來指導(dǎo)我們?nèi)绾斡脧牧硪环N思維模式去使用 C 語言。

值得注意的是,并不是所有使用C語言開發(fā)的項(xiàng)目,都必須以“面向?qū)ο蟆弊鳛橹笇?dǎo),有時(shí)候“面向過程”也不一定是壞事,需要根據(jù)實(shí)際項(xiàng)目情況,具體問題具體分析。

接下來,我們將嘗試使用 C 語言進(jìn)行面向?qū)ο蟪绦蜷_發(fā),務(wù)求使用 C 語言實(shí)現(xiàn)面向?qū)ο蟮囊恍┗咎匦?,先來說說封裝。

封裝就是把一個(gè)抽象事物的屬性和屬性的操作函數(shù)打包在一起,外界的模塊只能通過這個(gè)抽象事物對外提供的函數(shù)接口,對其屬性進(jìn)行訪問。

在C++或其他高級(jí)語言中,封裝通常被稱作“類”。而 C 語言一般使用結(jié)構(gòu)體對事物進(jìn)行封裝。

說人話就是,封裝,即“封閉包裝起來”,俗稱“打包”。把事物里面一些相近類似的特征進(jìn)行打包(打包的過程一般稱作“抽象”),這樣就是封裝了。

舉個(gè)例子:大多數(shù)動(dòng)物,都有眼睛耳朵嘴巴鼻子,把“五官”提取出來進(jìn)行封裝,這個(gè)封裝就成為了大多數(shù)動(dòng)物共有的東西。

頭文件 coordinate.h

#ifndef __COORDINATE_H_
#define __COORDINATE_H_

//聲明一個(gè)位置類,屬性為坐標(biāo)x,y
typedef struct coordinate{
    short int x;
    short int y;
}COORDINATE_T,*P_COORDINATE_T;

extern P_COORDINATE_T coordinate_create(short int x,short int y);
extern void coordinate_destroy(P_COORDINATE_T p_coordinate);
extern void coordinate_moveby(P_COORDINATE_T p_coordinate,short int dx,short int dy);
extern short int coordinate_get_x(P_COORDINATE_T p_coordinate);
extern short int coordinate_get_y(P_COORDINATE_T p_coordinate);
extern void coordinate_test_function(void);
#endif // !__COORDINATE_H_

源文件 coordinate.c

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "inc/coordinate.h"

//創(chuàng)建一個(gè)coordinate對象
P_COORDINATE_T coordinate_create(short int x,short int y)
{
    if((x < 0) || (y < 0)){
        printf("coordinate creat error! x or y can not be less than zero n");
        return NULL;
    }

    P_COORDINATE_T p_coordiante = NULL;
    p_coordiante = (P_COORDINATE_T)malloc(sizeof(COORDINATE_T));

    if(NULL != p_coordiante){
        p_coordiante->x = x;
        p_coordiante->y = y;        
    }
    else printf("coordinate malloc error! n");
         
    return p_coordiante;
}

//銷毀一個(gè)coordinate對象
void coordinate_destroy(P_COORDINATE_T p_coordiante)
{
    if(NULL != p_coordiante){
        free(p_coordiante);
        p_coordiante = NULL;
    }
}

//修改coordinate的屬性值
void coordinate_moveby(P_COORDINATE_T p_coordiante,short int dx,short int dy)
{
    if(NULL != p_coordiante){
        p_coordiante->x += dx;
        p_coordiante->y += dy;
    }
}

//獲取coordinate的屬性值x
short int coordinate_get_x(P_COORDINATE_T p_coordiante)
{  
    return (NULL != p_coordiante) ? p_coordiante->x : -1;
}

//獲取coordinate的屬性值y
short int coordinate_get_y(P_COORDINATE_T p_coordiante)
{
    return (NULL != p_coordiante) ? p_coordiante->y : -1;
}

代碼比較簡單,在頭文件 coordinate.h里面,通過結(jié)構(gòu)體封裝了一個(gè)coordinate類,里面有兩個(gè)坐標(biāo)屬性 x 和 y 。

coordinate_create 函數(shù)主要用于創(chuàng)建一個(gè) P_COORDINATE_T 類型的對象,并為其分配內(nèi)存空間,內(nèi)存分配成功后,設(shè)置兩個(gè)坐標(biāo)屬性的初始值,最后返回申請成功的對象指針。

coordinate_destroy 主要是釋放對象之前申請的內(nèi)存空間,然后把對象指針重置為NULL。

其他的操作函數(shù),主要是對類對象的屬性進(jìn)行操作,比如獲取 x 和 y 的屬性值,重置坐標(biāo)的屬性值。

以下是測試函數(shù),在主函數(shù)中調(diào)用,即可測試類coordinate對外提供的接口。

void coordinate_test_function(void)
{
    P_COORDINATE_T p_coordiante_1 = NULL;
    P_COORDINATE_T p_coordiante_2 = NULL;

    p_coordiante_1 = (P_COORDINATE_T)coordinate_create(100,200);
    p_coordiante_2 = (P_COORDINATE_T)coordinate_create(10,20);

    if((NULL == p_coordiante_1) || (NULL == p_coordiante_2)){
        printf("p_coordiante_1 or p_coordiante_2 create error! n");
        return;
    }

    printf("p_coordiante_1 x = %d, y = %d n",coordinate_get_x(p_coordiante_1), coordinate_get_y(p_coordiante_1));
    printf("p_coordiante_2 x = %d, y = %d n",coordinate_get_x(p_coordiante_2), coordinate_get_y(p_coordiante_2));

    coordinate_moveby(p_coordiante_1,50,50);
    coordinate_moveby(p_coordiante_2,50,50);

    printf("after moveby p_coordiante_1 x = %d, y = %d n",coordinate_get_x(p_coordiante_1), coordinate_get_y(p_coordiante_1));
    printf("after moveby p_coordiante_2 x = %d, y = %d n",coordinate_get_x(p_coordiante_2), coordinate_get_y(p_coordiante_2));

    coordinate_destroy(p_coordiante_1);
    coordinate_destroy(p_coordiante_2);
}

測試代碼比較簡單,主要是創(chuàng)建了兩個(gè) P_COORDINATE_T 類型的對象,然后打印其坐標(biāo)初始值,再通過對外提供的函數(shù)修改其坐標(biāo)值,然后再打印出來,最后銷毀之前創(chuàng)建的對象。測試函數(shù)運(yùn)行后,結(jié)果如下所示:

p_coordiante_1 x = 100, y = 200 
p_coordiante_2 x = 10, y = 20 
after moveby p_coordiante_1 x = 150, y = 250 
after moveby p_coordiante_2 x = 60, y = 70

從上述代碼可以看出,使用結(jié)構(gòu)體可以很好地對數(shù)據(jù)進(jìn)行封裝,并且需要通過指定的操作函數(shù)對結(jié)構(gòu)體內(nèi)的數(shù)據(jù)進(jìn)行訪問。

每個(gè)操作函數(shù)的第一個(gè)參數(shù)是對象本身的指針,通過這個(gè)指針去訪問具體對象里面的屬性。這是因?yàn)樵?C 語言中不存在像 C++ 語言那樣的 this 指針,所以我們只能顯式地通過函數(shù)傳參的方式,讓函數(shù)內(nèi)部可以訪問對象實(shí)例的其他成員。

對于對象屬性的各種操作函數(shù),還可以使用函數(shù)指針的方式,放入結(jié)構(gòu)體內(nèi)進(jìn)行封裝。但為了便于理解,本文并沒有采用這種方法。

源碼下載地址:https://github.com/embediot/my_program_test

感謝閱讀!

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
NX2012SA-32.768K-STD-MUB-1 1 Nihon Dempa Kogyo Co Ltd Parallel - Fundamental Quartz Crystal, 0.032768MHz Nom, ROHS COMPLIANT PACKAGE-2
$7.18 查看
AT24C256C-SSHL-B 1 Microchip Technology Inc IC EEPROM 256KBIT 1MHZ 8SOIC
$0.74 查看
LAN9303I-ABZJ 1 SMSC Ethernet Transceiver, 8 X 8 MM, ROHS COMPLIANT, QFN-56
$8.26 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜