楊韜
?。◤V州致遠(yuǎn)電子股份有限公司,,廣東 廣州 510660)
摘要: C語(yǔ)言在嵌入式軟件開發(fā)中被廣泛使用,但由于開發(fā)人員和應(yīng)用場(chǎng)景等原因,,面向?qū)ο?/a>,、設(shè)計(jì)模式等優(yōu)秀的軟件開發(fā)方法始終沒有很好地運(yùn)用起來(lái)。時(shí)至今日,,物聯(lián)網(wǎng)等應(yīng)用的興起給嵌入式軟件開發(fā)帶來(lái)新的挑戰(zhàn),,而傳統(tǒng)的面向過程開發(fā)方法已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,,有必要在嵌入式軟件開發(fā)中引入面向?qū)ο?、設(shè)計(jì)模式等優(yōu)秀的軟件開發(fā)方法。面向?qū)ο笫乾F(xiàn)在軟件方法的根基,,繼承是面向?qū)ο蟮娜筇匦灾?,本文結(jié)合C語(yǔ)言的特性,對(duì)使用C語(yǔ)言實(shí)現(xiàn)繼承進(jìn)行了討論,。
關(guān)鍵詞: C語(yǔ)言,;面向?qū)ο螅?a class="innerlink" href="http://forexkbc.com/tags/類" title="類" target="_blank">類;繼承
中圖分類號(hào):TP312文獻(xiàn)標(biāo)識(shí)碼:ADOI: 10.19358/j.issn.1674-7720.2016.24.005
引用格式:楊韜. 用C語(yǔ)言實(shí)現(xiàn)繼承的研究[J].微型機(jī)與應(yīng)用,,2016,35(24):16-18.
0引言
物聯(lián)網(wǎng)等應(yīng)用的興起,,給嵌入式軟件開發(fā)帶來(lái)新的挑戰(zhàn),而傳統(tǒng)的面向過程開發(fā)方法已經(jīng)難以支撐這些復(fù)雜的應(yīng)用,。因此,,有必要在嵌入式軟件開發(fā)中引入面向?qū)ο蟆⒃O(shè)計(jì)模式等優(yōu)秀的軟件開發(fā)方法,。在C++等面向?qū)ο笳Z(yǔ)言中對(duì)類做了原生的支持,,提供了class這一數(shù)據(jù)類型,能夠很自然地支持繼承這一面向?qū)ο筇匦?。盡管C語(yǔ)言并不支持class,,但是能夠通過一些特殊的處理來(lái)模擬繼承,本文將討論如何使用C語(yǔ)言來(lái)實(shí)現(xiàn)繼承這一面向?qū)ο筇匦浴?/p>
1基本概念[1]
1.1類
面向?qū)ο笥腥筇匦裕悍庋b,、繼承,、多態(tài),這些特性主要通過類來(lái)體現(xiàn),。類就是一個(gè)封裝了屬性以及相關(guān)操作的代碼的邏輯實(shí)體,。
類具有屬性,它是對(duì)象狀態(tài)的抽象,,用數(shù)據(jù)結(jié)構(gòu)來(lái)描述類的屬性,。
類具有方法,它是對(duì)象行為的抽象,,用方法名和實(shí)現(xiàn)該操作的方法來(lái)描述,。
除了封裝屬性和操作外,類還具有訪問控制的能力,,比如,,某些屬性和方法可以是私有的,不能被外界訪問,。通過訪問控制,,能夠?qū)?nèi)部數(shù)據(jù)提供不同級(jí)別的保護(hù),以防止外界意外地改變或使用了私有部分,。不同的編程語(yǔ)言提供的訪問控制等級(jí)不盡相同,,但都有公有、私有兩個(gè)等級(jí),。
類是抽象的數(shù)據(jù)類型,,在內(nèi)存中并不存在(Python等動(dòng)態(tài)語(yǔ)言除外),只有類的實(shí)例存在于內(nèi)存中,。
1.2繼承
在定義一個(gè)類的時(shí)候,,可以在一個(gè)已經(jīng)存在的類的基礎(chǔ)上進(jìn)行,,新的類自動(dòng)繼承已存在類的公有屬性和方法,在此基礎(chǔ)上可以添加新的屬性或方法,,這種特性就是繼承,。被繼承的類稱作父類或基類,繼承而得到的新類稱作子類或派生類,。通過繼承可以使開發(fā)的軟件具有擴(kuò)展性,,簡(jiǎn)化了類的創(chuàng)建工作量,提高了代碼復(fù)用性,。
圖1為類繼承的UML圖,,圖中定義了兩個(gè)類,兩個(gè)類用空心三角箭頭連接,,箭頭指向的就是父類Human,,箭尾就是子類Chinese。Chinese類繼承了Human類,,Chinese類自動(dòng)擁有Human的公有屬性和方法(即name,、buy()和talk()),此外,,Chinese類新添加了方法play_mahjong(),。通俗點(diǎn)描述就是:中國(guó)人是人類,有名字,,能夠講話和購(gòu)物,,除此之外,還能打麻將,。
繼承分為單重繼承和多重繼承:子類只繼承一個(gè)父類,,稱為單重繼承,如圖1所示,;子類繼承多個(gè)父類,,稱為多重繼承,如圖2所示,。為了避免二義性,,不推薦使用多重繼承,本文只討論單重繼承,。
2類的C語(yǔ)言實(shí)現(xiàn)
在C語(yǔ)言中可以使用.c,、.h和結(jié)構(gòu)體來(lái)實(shí)現(xiàn)類,以圖1中Human類為例,,可以使用human.h,、human.c、struct human三個(gè)元素來(lái)完成封裝,,human.c為human.h中函數(shù)聲明的實(shí)現(xiàn),,本文不討論這些細(xì)節(jié),,只給出human.h的關(guān)鍵代碼片段:
程序清單1Human類C語(yǔ)言實(shí)現(xiàn)
// human.h
typedef struct human {
const char *name;
int _money;
} human_t;
human_t *human_init(human_t *p_this,
const char *name,
int money);
voidhuman_talk(human_t *p_this,
const char *p_words);
voidhuman_buy (human_t *p_this,
const char *p_something,
unsigned price,
unsigned count);
voidhuman_deinit(human_t *p_this);
3繼承的C語(yǔ)言實(shí)現(xiàn)
3.1C語(yǔ)言不能實(shí)現(xiàn)嚴(yán)格的繼承
一種常見的用C語(yǔ)言實(shí)現(xiàn)繼承的方法如下面的代碼所示:
/* 父類 /基類*/
struct parent {
int a;
};
/* 子類/派生類 */
struct child {
struct parent base; /* 第一個(gè)成員為基類 */
int b;
};
void foo (void)
{
struct childfoo;
struct child *p_child;
struct parent*p_parent;
p_child = &foo;
p_parent = (struct parent *)p_child;
/* 將子類轉(zhuǎn)換為父類 */
p_parent->a = 100;/* 訪問父類成員 */
}
上面的代碼中定義了一個(gè)父類和子類,foo()函數(shù)中實(shí)例化了一個(gè)子類對(duì)象,,使用強(qiáng)制類型轉(zhuǎn)換將子類對(duì)象的指針p_child轉(zhuǎn)換為父類指針p_parent,,如此達(dá)到了訪問其父類成員的效果。此方法有明顯的缺陷——使用了強(qiáng)制類型轉(zhuǎn)換,,而在C語(yǔ)言編程中是要避免使用強(qiáng)制類型轉(zhuǎn)換的,。如果要得到子類的父類,,推薦下面這種更安全的方法:
p_parent = &p_child->base;
對(duì)于很多面向?qū)ο缶幊陶Z(yǔ)言來(lái)說(shuō),,子類對(duì)象調(diào)用父類的屬性方法不需要顯式轉(zhuǎn)型,而C語(yǔ)言做不到這一點(diǎn),,比如,,不能通過p_child->a直接訪問父類的屬性,因此,,嚴(yán)格意義上說(shuō)“C語(yǔ)言不能實(shí)現(xiàn)嚴(yán)格的繼承”,。
3.2用C語(yǔ)言實(shí)現(xiàn)繼承
在前面一節(jié)中指出“C語(yǔ)言不能實(shí)現(xiàn)嚴(yán)格的繼承”,盡管如此,,由于繼承在軟件設(shè)計(jì)中時(shí)有使用,,因此用C語(yǔ)言實(shí)現(xiàn)繼承仍是必要的。盡管繼承實(shí)現(xiàn)的效果不如C++等面向?qū)ο笳Z(yǔ)言那么完美,,但還是可以達(dá)到實(shí)用程度的,。
以圖1為例,Human為父類,,Chinese為基類,。Human類的實(shí)現(xiàn)請(qǐng)參考程序清單1,Chinese類的實(shí)現(xiàn)(chinese.h)請(qǐng)參考程序清單2,,chinese.c為chinese.h中函數(shù)聲明的實(shí)現(xiàn),,本文不討論這些細(xì)節(jié)。
程序清單2Chinese類C語(yǔ)言實(shí)現(xiàn)
#include "human.h"
typedef struct chinese {
human_t super;
const char *city;
} chinese_t;
#define CHINESE_TO_HUMAN(p_chinese) \ (&((p_chinese)->super))
chinese_t *chinese_init (chinese_t *p_this, const char *name, int money, const char *city);
chinese_t *chinese_create(const char *name, unsigned int money, const char *city);
void chinese_play_mahjong (chinese_t *p_this);
void chinese_deinit (chinese_t *p_this);
void chinese_delete (chinese_t **pp_this);
Chinese類繼承Human類體現(xiàn)在struct chinese 結(jié)構(gòu)體中嵌入了其父類struct human成員,,但這并不是完美的繼承,,如果要訪問父類的屬性和方法,需要先調(diào)用CHINESE_TO_HUMAN()將子類指針轉(zhuǎn)型為父類指針,。需要注意的是CHINESE_TO_HUMAN()并沒有使用強(qiáng)制類型轉(zhuǎn)換,,這意味著struct chinese的成員super可以放在任意位置,大大提高了使用的安全性和靈活性,。程序清單3展示了繼承相關(guān)特性的使用,。
程序清單3繼承的使用
chinese_txiaoming, *p_xiaoming;
human_t*p_human;
p_ xiaoming = chinese_create(
"XiaoMing", 100, "Beijing"); // 實(shí)例化子類
p_human = CHINESE_TO_HUMAN(p_ xiaoming);
// 向上轉(zhuǎn)型,得到父類引用
human_talk(p_human, "Ni Hao!\\n");// 調(diào)用父類方法
chinese_play_mahjong(p_laowang);// 調(diào)用子類方法
4結(jié)論
本文通過使用C語(yǔ)言實(shí)現(xiàn)Chinese類對(duì)Human類的繼承,,討論了如何使用C語(yǔ)言來(lái)實(shí)現(xiàn)繼承,。在C++等面向?qū)ο笳Z(yǔ)言中對(duì)類做了原生的支持,,能夠很容易地實(shí)現(xiàn)。盡管C語(yǔ)言不能實(shí)現(xiàn)嚴(yán)格意義上的繼承,,但是通過在一個(gè)結(jié)構(gòu)體中嵌入另一個(gè)結(jié)構(gòu)體的方式,,也能達(dá)到繼承的效果,與其他面向?qū)ο笳Z(yǔ)言不同的是,,調(diào)用父類方法時(shí)需要顯式轉(zhuǎn)型,。
參考文獻(xiàn)
[1] 百度百科. 面向?qū)ο螅跡B/OL].(2012 12 12)[2016 08 08]http://baike.baidu.com/linkurl=6XlXEOSlrKn87S7SJv4U WSX7EjstoDVmwJ13OAodXUrUrnZkVg3ntPFirEy5c6mqObZZ OevQI6K3Ungq1Mq.