加入星計(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
271
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師,關(guān)注我,一起變得更加優(yōu)秀!

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

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

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

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

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

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

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

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

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

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

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

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

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

頭文件 coordinate.h

#ifndef __COORDINATE_H_
#define __COORDINATE_H_

//聲明一個位置類,屬性為坐標(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)建一個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;
}

//銷毀一個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)體封裝了一個coordinate類,里面有兩個坐標(biāo)屬性 x 和 y 。

coordinate_create 函數(shù)主要用于創(chuàng)建一個 P_COORDINATE_T 類型的對象,并為其分配內(nèi)存空間,內(nèi)存分配成功后,設(shè)置兩個坐標(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)建了兩個 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)行訪問。

每個操作函數(shù)的第一個參數(shù)是對象本身的指針,通過這個指針去訪問具體對象里面的屬性。這是因?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

感謝閱讀!

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險(xiǎn)等級 參考價格 更多信息
FODM121AR2V 1 onsemi 4-Pin Full Pitch Mini-Flat Package Phototransistor Optocouplers, 2500-REEL
$0.21 查看
CSTCE16M0V13C99-R0 1 Murata Manufacturing Co Ltd Ceramic Resonator, 16MHz Nom, SMD, 3 PIN

ECAD模型

下載ECAD模型
$1.6 查看
CSTCC8M38G53-R0 1 Murata Manufacturing Co Ltd Ceramic Resonator,
暫無數(shù)據(jù) 查看

相關(guān)推薦

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