日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式教程
[導(dǎo)讀]封裝,在C語(yǔ)言編程中,大部分時(shí)候用一個(gè)函數(shù)調(diào)用(API)將一個(gè)復(fù)雜過程的細(xì)節(jié)屏蔽起來,用戶不需要了解細(xì)節(jié),只需要調(diào)用該函數(shù)就能實(shí)現(xiàn)相應(yīng)的行為。

很多程序員小白在剛剛踏入職場(chǎng),做程序開發(fā)工作的時(shí)候,經(jīng)常會(huì)被項(xiàng)目經(jīng)理叫去喝茶。

小白,你寫的這代碼耦合太嚴(yán)重啦,簡(jiǎn)直沒有設(shè)計(jì)可言,更不要說擴(kuò)展性和靈活性,所有的功能都定義在一個(gè)類里,這樣隨著功能的增多,代碼就越來越復(fù)雜。你趕緊把代碼拆分一下,各功能進(jìn)行一下代碼封裝。

1那什么是封裝呢?

封裝,在C語(yǔ)言編程中,大部分時(shí)候用一個(gè)函數(shù)調(diào)用(API)將一個(gè)復(fù)雜過程的細(xì)節(jié)屏蔽起來,用戶不需要了解細(xì)節(jié),只需要調(diào)用該函數(shù)就能實(shí)現(xiàn)相應(yīng)的行為。例如吃飯函數(shù),將盛飯,動(dòng)筷子,夾菜,張嘴,咀嚼,下咽等細(xì)節(jié)屏蔽起來,我們只需要調(diào)用吃飯函數(shù),默認(rèn)就實(shí)現(xiàn)了一遍這樣的流程。

面向?qū)ο笏枷胫械姆庋b使用更廣泛,即一個(gè)對(duì)象類(C語(yǔ)言中用結(jié)構(gòu)體代替),需要隱藏用戶不需要也不應(yīng)該知道的行為和屬性。用戶在訪問對(duì)象時(shí),不需要了解被封裝的對(duì)象和屬性,就能使用該對(duì)象類,同時(shí)對(duì)象類也應(yīng)該通過權(quán)限設(shè)置,禁止用戶過多地了解被封裝的對(duì)象屬性與行為。

封裝的思想都是為了讓用戶不需要了解對(duì)象過多的細(xì)節(jié),就能直接通過API來使用對(duì)象,從而達(dá)到模塊化編程,程序員分工合作,各自負(fù)責(zé)維護(hù)自己負(fù)責(zé)模塊對(duì)象細(xì)節(jié)的作用。這個(gè)原則普遍存在于現(xiàn)實(shí)生活中,在軟件開發(fā)領(lǐng)域也始終提倡著。

2為什么要進(jìn)行代碼封裝?

我們寫程序是用來解決問題的,而且要解決的是現(xiàn)實(shí)中的問題,所以我們需要將現(xiàn)實(shí)問題轉(zhuǎn)化為符號(hào)化的問題,而現(xiàn)實(shí)中的問題是由個(gè)體所組成的,所以我們將數(shù)據(jù)和處理數(shù)據(jù)的方法封裝起來形成一個(gè)個(gè)體,這個(gè)個(gè)體在問題里面有專門的功能,比如一張紙可以折疊,一支筆可以寫,這樣有助于我們以自身的角度進(jìn)行思考分析,這就是面向?qū)ο?。如果用面向過程的思路,會(huì)導(dǎo)致問題與程序之間的轉(zhuǎn)化不好處理,可能使解決問題出現(xiàn)偏差。

封裝的過程,其實(shí)就是對(duì)事物進(jìn)行抽象的過程,也是對(duì)事物進(jìn)行認(rèn)識(shí)的過程,我們從開始到現(xiàn)在,封裝的層次越來越深,處理的問題也越來越復(fù)雜。因?yàn)槲覀冃枰砬鍙?fù)雜問題的內(nèi)部規(guī)律,從而找出解決問題的辦法,而深層次的封裝使問題恢復(fù)成本來的樣子就是一種解決辦法。所以說封裝是在面對(duì)軟件復(fù)雜度增加,開發(fā)過程中遇到各種瓶頸時(shí),為了解決這些問題而提出的,通過封裝可以達(dá)到模塊化編程,程序員分工合作,各自負(fù)責(zé)維護(hù)自己負(fù)責(zé)模塊對(duì)象細(xì)節(jié)的作用。當(dāng)封裝的程度達(dá)到了一定的水平,就是面向?qū)ο蟮某绦蛟O(shè)計(jì)思想。

3什么是面向?qū)ο笏枷?,和面向過程有什么不同?

所謂面向?qū)ο蟮乃枷肫鋵?shí)就是一種在代碼編寫之上的軟件系統(tǒng)結(jié)構(gòu)設(shè)計(jì)的思想,和語(yǔ)言無關(guān),并不是C++或者JAVA 、Python等語(yǔ)言才有的。面向?qū)ο笏枷耄请S著軟件系統(tǒng)的復(fù)雜度越來越高,面對(duì)大規(guī)模軟件系統(tǒng)設(shè)計(jì)的問題,而提出的一種管理大型軟件系統(tǒng)設(shè)計(jì)的思想。只是在C語(yǔ)言出現(xiàn)時(shí),計(jì)算機(jī)軟硬件系統(tǒng)還在起步階段,面向?qū)ο蟮乃枷肷形窗l(fā)展,因而C語(yǔ)言中缺乏面向?qū)ο笙嚓P(guān)的核心關(guān)鍵詞語(yǔ)法的支持。而JAVA、Python等一些1990年代之后問世的語(yǔ)言,受到C++語(yǔ)言影響以及面向?qū)ο笏枷氲闹饾u流行,在語(yǔ)法層面就提供了面向?qū)ο蟮暮诵年P(guān)鍵詞支持,可以說在處理面向?qū)ο髥栴}上具有先天優(yōu)勢(shì)。雖然C語(yǔ)言不支持很多面向?qū)ο蟮暮诵年P(guān)鍵詞,但是隨著Linux內(nèi)核,F(xiàn)fmpeg,Nginx等大規(guī)模以C語(yǔ)言編寫的開源軟件項(xiàng)目的發(fā)展與推廣,C語(yǔ)言遇到的軟件復(fù)雜度增加以及系統(tǒng)設(shè)計(jì)與系統(tǒng)長(zhǎng)期維護(hù)的問題,與JAVA、C++編程遇到的復(fù)雜度問題是想通的。并且,面向?qū)ο笏枷胍彩怯捎陂_發(fā)者們?cè)陂_發(fā)過程中遇到瓶頸才提出來的,這些問題,不管是用C語(yǔ)言編程還是JAVA編程,都會(huì)客觀存在。因而用C語(yǔ)言模擬JAVA等面向?qū)ο蟮恼Z(yǔ)言,采用面向?qū)ο蟮乃枷脒M(jìn)行系統(tǒng)頂層設(shè)計(jì)是很有必要的。

面向過程與面向?qū)ο蟮乃枷胗猛静煌?,沒有好壞之分。面向?qū)ο笏枷敫鼉A向于程序之上的頂層設(shè)計(jì)與程序系統(tǒng)結(jié)構(gòu)設(shè)計(jì),然后真正要實(shí)現(xiàn)一個(gè)函數(shù)細(xì)節(jié)的時(shí)候,還是需要面向過程地分析細(xì)節(jié)如何實(shí)現(xiàn),需要初始化哪些變量,注冊(cè)哪些結(jié)構(gòu),設(shè)置哪些寄存器等面向過程的問題。

4在C語(yǔ)言中實(shí)現(xiàn)面向?qū)ο蟮乃枷?/strong>

既然面向?qū)ο笫欠N思想,任何語(yǔ)言都可以實(shí)現(xiàn),而且這種思想最重要的幾個(gè)特性是封裝,繼承,多態(tài)。那在C語(yǔ)言中如何實(shí)現(xiàn)呢?

在正式介紹C語(yǔ)言實(shí)現(xiàn)封裝,繼承和多態(tài)事前,先介紹一下C語(yǔ)言中的幾個(gè)概念和語(yǔ)法。

4.1基本知識(shí)

(1)結(jié)構(gòu)體

在C語(yǔ)言中,常把一個(gè)對(duì)象用結(jié)構(gòu)體進(jìn)行封裝,這樣便于對(duì)對(duì)象進(jìn)行操作,比如:

strcut Point{

int x;

int y;

};

結(jié)構(gòu)體可以嵌套。因而可以把一個(gè)結(jié)構(gòu)體當(dāng)成另一個(gè)結(jié)構(gòu)體的成員,如:

struct Circle {

struct Point point_;

int radius;

};

該結(jié)構(gòu)體與以下定義完全一樣(包括內(nèi)存布置都一樣):

struct Circle {

int x;

int y;

int radius;

};

(2)函數(shù)指針

函數(shù)指針是指針的一種,它指向函數(shù)的首地址(函數(shù)的函數(shù)名即為函數(shù)的首地址),可以通過函數(shù)指針來調(diào)用函數(shù)。

如函數(shù):

int func(int a[], int n);

可以這樣聲明函數(shù)指針:

int (*pFunc)(int a[], int n);

這樣使用:

pFunc = func;

(*pFunc)(a, n);【或者PFunc(a, n)】

可以用typedef定義一個(gè)函數(shù)指針類型,如:

typdef int (*FUNC)(int a[], int n)

可以這樣使用:

int cal_a(FUNC fptr, int a[], int n)

{

//實(shí)現(xiàn)體

}

(3)extern與static

extern和static是C語(yǔ)言中的兩個(gè)修飾符,extern可用于修飾函數(shù)或者變量,表示該變量或者函數(shù)在其他文件中進(jìn)行了定義;static也可用于修飾函數(shù)或者變量,表示該函數(shù)或者變量只能在該文件中使用??衫盟鼈儗?duì)數(shù)據(jù)或者函數(shù)進(jìn)行隱藏或者限制訪問權(quán)限。

4.2封裝

在C語(yǔ)言中,可以用結(jié)構(gòu)+函數(shù)指針來模擬類的實(shí)現(xiàn),而用這種結(jié)構(gòu)定義的變量就是對(duì)象。封裝的主要含義是隱藏內(nèi)部的行為和信息,使用者只用看到對(duì)外提供的接口和公開的信息。有兩種方法實(shí)現(xiàn)封裝:

(1) 利用C語(yǔ)言語(yǔ)法。在頭文件中聲明,在C文件中真正定義它。

這樣可以隱藏內(nèi)部信息,因?yàn)橥獠坎恢缹?duì)象所占內(nèi)存的大小,所以不能靜態(tài)的創(chuàng)建該類的對(duì)象,只能調(diào)用類提供的創(chuàng)建函數(shù)才能創(chuàng)建。這種方法的缺陷是不支持繼承,因?yàn)樽宇愔械貌坏饺魏侮P(guān)于父類的信息。如:

//頭文件:point.h

#ifndef POINT_H

#define POINT_H

struct Point;

typedef struct Point point;

point * new_point(); //newer a point object

void free_point(point *point_);// free the allocated space

#endif

//C文件:point.c

#include”point.h”

strcut Point

{

int x;

int y;

};

point * new_point()

{

point * new_point_ = (point *) malloc(sizeof(point));

return new_point_;

}

void free_point(point *point_)

{

if(point_ == NULL)

return;

free(point_);

}

(2) 把私有數(shù)據(jù)信息放在一個(gè)不透明的priv變量或者結(jié)構(gòu)體中。只有類的實(shí)現(xiàn)代碼才知道priv或者結(jié)構(gòu)體的真正定義。如:

#ifndef POINT _H

#define POINT_H

typedef struct Point point;

typedef struct pointPrivate pointPrivate;

strcut Point

{

Struct pointPrivate *pp;

};

int get_x(point *point_);

int get_y(point *point_);

point * new_point(); //newer a point object

void free_point(point *point_);// free the allocated space

#endif

//C文件:point.c

#include”point.h”

struct pointPrivate

{

int x;

int y;

}

int get_x(point *point_)

{

return point_->pp->x;

}

int get_y(point *point_)

{

return point_->pp->y;

}

//others…..

4.3繼承

在C語(yǔ)言中,可以利用“結(jié)構(gòu)在內(nèi)存中的布局與結(jié)構(gòu)的聲明具有一致的順序”這一事實(shí)實(shí)現(xiàn)繼承。

比如我們要設(shè)計(jì)一個(gè)作圖工具,其中可能涉及到的對(duì)象有Point(點(diǎn)),Circle(圓),由于圓是由點(diǎn)組成的,所有可以看成Circle繼承自Point。另外,Point和Circle都需要空間申請(qǐng),空間釋放等操作,所有他們有共同的基類Base。

//內(nèi)存管理類new.h

#ifndef NEW_H

#define NEW_H

void * new (const void * class, ...);

void delete (void * item);

void draw (const void * self);

#endif

//內(nèi)存管理類的C文件:new.c

#include “new.h”

#include “base.h”

void * new (const void * _base, ...)

{

const struct Base * base = _base;

void * p = calloc(1, base->size);

assert(p);

* (const struct Base **) p = base;

if (base ->ctor)

{

va_list ap;

va_start(ap, _base);

p = base ->ctor(p, &ap);

va_end(ap);

}

return p;

}

void delete (void * self)

{

const struct Base ** cp = self;

if (self && * cp && (* cp) —> dtor)

self = (* cp) —>dtor(self);

free(self);

}

void draw (const void * self)

{

const struct Base * const * cp = self;

assert(self &&* cp && (* cp)->draw);

(* cp) ->draw(self);

}

//基類:base.h

#ifndef BASE_H

#define BASE_H

struct Base

{

size_t size; //類所占空間

void * (* ctor) (void * self, va_list * app); //構(gòu)造函數(shù)

void * (* dtor) (void * self); //析構(gòu)函數(shù)

void (* draw) (const void * self); //作圖

};

#endif

//Point頭文件(對(duì)外提供的接口):point.h

#ifndef POINT_H

#define POINT_H

extern const void * Point; /* 使用方法:new (Point, x, y); */

#endif

//Point內(nèi)部頭文件(外面看不到):point.r

#ifndef POINT_R

#define POINT_R

struct Point

{

const void * base; //繼承,基類指針,放在第一個(gè)位置,const是防止修改

int x, y; //坐標(biāo)

}

#endif

//Point的C文件:point.c

#include “point.h”

#include “new.h”

#include “point.h”

#include “point.r”

static void * Point_ctor (void * _self, va_list * app)

{

struct Point * self = _self;

self ->x = va_arg(* app, int);

self ->y = va_arg(* app, int);

return self;

}

static void Point_draw (const void * _self)

{

const struct Point * self = _self;

printf(“draw (%d,%d)”, self -> x, self -> y);

}

static const struct Base _Point = {

sizeof(struct Point), Point_ctor, 0, Point_draw

};

const void * Point = & _Point;

//測(cè)試程序:main.c

#include “point.h”

#include “new.h”

int main (int argc, char ** argv)

{

void * p = new(Point, 1, 2);

draw(p);

delete(p);

}

同樣,Circle要繼承Point,則可以這樣:

struct Circle

{

const struct Point point; //放在第一位,可表繼承

int radius;

};

4.3多態(tài)

可以是用C語(yǔ)言中的萬(wàn)能指針void* 實(shí)現(xiàn)多態(tài),接上面的例子:

//測(cè)試main.c

void * p = new(Point, 1, 2);

void * pp = new(Circle, 1, 2);

draw(p); //draw函數(shù)實(shí)現(xiàn)了多態(tài)

draw(pp);

delete(p);

delete(pp);

C語(yǔ)言能夠模擬實(shí)現(xiàn)面向?qū)ο笳Z(yǔ)言具有的特性,包括:多態(tài),繼承,封裝等,現(xiàn)在很多開源軟件都了用C語(yǔ)言實(shí)現(xiàn)了這幾個(gè)特性,包括大型開源數(shù)據(jù)庫(kù)系統(tǒng)postgreSQL,可移植的C語(yǔ)言面向?qū)ο罂蚣蹽Object,無線二進(jìn)制運(yùn)行環(huán)境BREW。采用C語(yǔ)言實(shí)現(xiàn)多態(tài),繼承,封裝,能夠讓軟件有更好的可讀性,可擴(kuò)展性。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

在這篇文章中,小編將對(duì)PLC的相關(guān)內(nèi)容和情況加以介紹以幫助大家增進(jìn)對(duì)它的了解程度,和小編一起來閱讀以下內(nèi)容吧。

關(guān)鍵字: PLC 模塊化 程序

鏈表作為一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),在程序設(shè)計(jì)中扮演著重要角色。掌握鏈表的高效操作技巧,特別是逆序、合并和循環(huán)檢測(cè),對(duì)于提升算法性能和解決復(fù)雜問題至關(guān)重要。本文將詳細(xì)介紹這些操作的C語(yǔ)言實(shí)現(xiàn),并分析其時(shí)間復(fù)雜度。

關(guān)鍵字: 鏈表 C語(yǔ)言

在C/C++多文件編程中,靜態(tài)變量(static)與全局變量的作用域規(guī)則看似簡(jiǎn)單,實(shí)則暗藏諸多陷阱。開發(fā)者若未能準(zhǔn)確理解其鏈接屬性與生命周期,極易引發(fā)難以調(diào)試的內(nèi)存錯(cuò)誤、競(jìng)態(tài)條件以及維護(hù)災(zāi)難。本文將深入剖析這兩類變量的作...

關(guān)鍵字: 靜態(tài)變量 全局變量 C語(yǔ)言

在嵌入式系統(tǒng)和服務(wù)器開發(fā)中,日志系統(tǒng)是故障排查和運(yùn)行監(jiān)控的核心組件。本文基于Linux環(huán)境實(shí)現(xiàn)一個(gè)輕量級(jí)C語(yǔ)言日志庫(kù),支持DEBUG/INFO/WARN/ERROR四級(jí)日志分級(jí),并實(shí)現(xiàn)按大小滾動(dòng)的文件輪轉(zhuǎn)機(jī)制。該設(shè)計(jì)在某...

關(guān)鍵字: C語(yǔ)言 嵌入式系統(tǒng)

在嵌入式系統(tǒng)和底層驅(qū)動(dòng)開發(fā)中,C語(yǔ)言因其高效性和可控性成為主流選擇,但缺乏原生單元測(cè)試支持成為開發(fā)痛點(diǎn)。本文提出一種基于宏定義和測(cè)試用例管理的輕量級(jí)單元測(cè)試框架方案,通過自定義斷言宏和測(cè)試注冊(cè)機(jī)制,實(shí)現(xiàn)無需外部依賴的嵌入...

關(guān)鍵字: C語(yǔ)言 嵌入式系統(tǒng) 驅(qū)動(dòng)開發(fā)

在嵌入式系統(tǒng)開發(fā)中,實(shí)時(shí)操作系統(tǒng)(RTOS)的任務(wù)調(diào)度算法直接影響系統(tǒng)的響應(yīng)速度和資源利用率。時(shí)間片輪轉(zhuǎn)(Round-Robin, RR)作為一種經(jīng)典的公平調(diào)度算法,通過為每個(gè)任務(wù)分配固定時(shí)間片實(shí)現(xiàn)多任務(wù)并發(fā)執(zhí)行。本文將...

關(guān)鍵字: 實(shí)時(shí)操作系統(tǒng) RTOS C語(yǔ)言

在Linux設(shè)備驅(qū)動(dòng)開發(fā)中,等待隊(duì)列(Wait Queue)是實(shí)現(xiàn)進(jìn)程睡眠與喚醒的核心機(jī)制,它允許進(jìn)程在資源不可用時(shí)主動(dòng)放棄CPU,進(jìn)入可中斷睡眠狀態(tài),待資源就緒后再被喚醒。本文通過C語(yǔ)言模型解析等待隊(duì)列的實(shí)現(xiàn)原理,結(jié)合...

關(guān)鍵字: 驅(qū)動(dòng)開發(fā) C語(yǔ)言 Linux

在嵌入式系統(tǒng)開發(fā)中,C語(yǔ)言與匯編的混合編程是優(yōu)化性能、訪問特殊指令或硬件寄存器的關(guān)鍵技術(shù)。然而,內(nèi)聯(lián)匯編的語(yǔ)法差異和寄存器使用規(guī)則常導(dǎo)致難以調(diào)試的問題。本文以ARM Cortex-M和x86架構(gòu)為例,系統(tǒng)梳理內(nèi)聯(lián)匯編的核...

關(guān)鍵字: C語(yǔ)言 匯編混合編程

在計(jì)算機(jī)安全領(lǐng)域,緩沖區(qū)溢出攻擊長(zhǎng)期占據(jù)漏洞利用榜首。這種攻擊通過向程序緩沖區(qū)寫入超出其容量的數(shù)據(jù),覆蓋相鄰內(nèi)存區(qū)域(如返回地址),進(jìn)而實(shí)現(xiàn)任意代碼執(zhí)行。本文將深入探討棧保護(hù)機(jī)制與安全函數(shù)(如snprintf)的集成防御...

關(guān)鍵字: 棧保護(hù) 安全函數(shù) C語(yǔ)言

在嵌入式系統(tǒng)和大規(guī)模數(shù)值計(jì)算等性能敏感場(chǎng)景中,程序優(yōu)化是提升效率的關(guān)鍵環(huán)節(jié)。gprof作為GNU工具鏈中的性能分析工具,能夠精準(zhǔn)定位CPU時(shí)間消耗熱點(diǎn)。本文通過實(shí)際案例演示gprof的三個(gè)核心使用步驟,幫助開發(fā)者快速識(shí)別...

關(guān)鍵字: C語(yǔ)言 gprof 熱點(diǎn)函數(shù)
關(guān)閉