楊 韜
(廣州致遠(yuǎn)電子股份有限公司,廣東 廣州 510660)
用C語言實(shí)現(xiàn)繼承的研究
楊 韜
(廣州致遠(yuǎn)電子股份有限公司,廣東 廣州 510660)
C語言在嵌入式軟件開發(fā)中被廣泛使用,但由于開發(fā)人員和應(yīng)用場景等原因,面向?qū)ο?、設(shè)計(jì)模式等優(yōu)秀的軟件開發(fā)方法始終沒有很好地運(yùn)用起來。時(shí)至今日,物聯(lián)網(wǎng)等應(yīng)用的興起給嵌入式軟件開發(fā)帶來新的挑戰(zhàn),而傳統(tǒng)的面向過程開發(fā)方法已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,有必要在嵌入式軟件開發(fā)中引入面向?qū)ο?、設(shè)計(jì)模式等優(yōu)秀的軟件開發(fā)方法。面向?qū)ο笫乾F(xiàn)在軟件方法的根基,繼承是面向?qū)ο蟮娜筇匦灾唬疚慕Y(jié)合C語言的特性,對(duì)使用C語言實(shí)現(xiàn)繼承進(jìn)行了討論。
C語言;面向?qū)ο?;類;繼承
物聯(lián)網(wǎng)等應(yīng)用的興起,給嵌入式軟件開發(fā)帶來新的挑戰(zhàn),而傳統(tǒng)的面向過程開發(fā)方法已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,有必要在嵌入式軟件開發(fā)中引入面向?qū)ο?、設(shè)計(jì)模式等優(yōu)秀的軟件開發(fā)方法。在C++等面向?qū)ο笳Z言中對(duì)類做了原生的支持,提供了class這一數(shù)據(jù)類型,能夠很自然地支持繼承這一面向?qū)ο筇匦?。盡管C語言并不支持class,但是能夠通過一些特殊的處理來模擬繼承,本文將討論如何使用C語言來實(shí)現(xiàn)繼承這一面向?qū)ο筇匦浴?/p>
1.1 類
面向?qū)ο笥腥筇匦裕悍庋b、繼承、多態(tài),這些特性主要通過類來體現(xiàn)。類就是一個(gè)封裝了屬性以及相關(guān)操作的代碼的邏輯實(shí)體。
類具有屬性,它是對(duì)象狀態(tài)的抽象,用數(shù)據(jù)結(jié)構(gòu)來描述類的屬性。
類具有方法,它是對(duì)象行為的抽象,用方法名和實(shí)現(xiàn)該操作的方法來描述。
除了封裝屬性和操作外,類還具有訪問控制的能力,比如,某些屬性和方法可以是私有的,不能被外界訪問。通過訪問控制,能夠?qū)?nèi)部數(shù)據(jù)提供不同級(jí)別的保護(hù),以防止外界意外地改變或使用了私有部分。不同的編程語言提供的訪問控制等級(jí)不盡相同,但都有公有、私有兩個(gè)等級(jí)。
類是抽象的數(shù)據(jù)類型,在內(nèi)存中并不存在(Python等動(dòng)態(tài)語言除外),只有類的實(shí)例存在于內(nèi)存中。
1.2 繼承
在定義一個(gè)類的時(shí)候,可以在一個(gè)已經(jīng)存在的類的基礎(chǔ)上進(jìn)行,新的類自動(dòng)繼承已存在類的公有屬性和方法,在此基礎(chǔ)上可以添加新的屬性或方法,這種特性就是繼承。被繼承的類稱作父類或基類,繼承而得到的新類稱作子類或派生類。通過繼承可以使開發(fā)的軟件具有擴(kuò)展性,簡化了類的創(chuàng)建工作量,提高了代碼復(fù)用性。
圖1 繼承
圖1為類繼承的UML圖,圖中定義了兩個(gè)類,兩個(gè)類用空心三角箭頭連接,箭頭指向的就是父類Human,箭尾就是子類Chinese。Chinese類繼承了Human類,Chinese類自動(dòng)擁有Human的公有屬性和方法(即name、buy()和talk()),此外,Chinese類新添加了方法play_mahjong()。通俗點(diǎn)描述就是:中國人是人類,有名字,能夠講話和購物,除此之外,還能打麻將。
繼承分為單重繼承和多重繼承:子類只繼承一個(gè)父類,稱為單重繼承,如圖1所示;子類繼承多個(gè)父類,稱為多重繼承,如圖2所示。為了避免二義性,不推薦使用多重繼承,本文只討論單重繼承。
圖2 多重繼承
在C語言中可以使用.c、.h和結(jié)構(gòu)體來實(shí)現(xiàn)類,以圖1中Human類為例,可以使用human.h、human.c、struct human三個(gè)元素來完成封裝,human.c為human.h中函數(shù)聲明的實(shí)現(xiàn),本文不討論這些細(xì)節(jié),只給出human.h的關(guān)鍵代碼片段:
程序清單1 Human類C語言實(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);
void human_talk (human_t *p_this,
const char *p_words);
void human_buy (human_t *p_this,
const char *p_something,
unsigned price,
unsigned count);
void human_deinit (human_t *p_this);
3.1 C語言不能實(shí)現(xiàn)嚴(yán)格的繼承
一種常見的用C語言實(shí)現(xiàn)繼承的方法如下面的代碼所示:
/* 父類 /基類*/
struct parent {
int a;
};
/* 子類/派生類 */
struct child {
struct parent base; /* 第一個(gè)成員為基類 */
int b;
};
void foo (void)
{
struct child foo;
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語言編程中是要避免使用強(qiáng)制類型轉(zhuǎn)換的。如果要得到子類的父類,推薦下面這種更安全的方法:
p_parent = &p_child->base;
對(duì)于很多面向?qū)ο缶幊陶Z言來說,子類對(duì)象調(diào)用父類的屬性方法不需要顯式轉(zhuǎn)型,而C語言做不到這一點(diǎn),比如,不能通過p_child->a直接訪問父類的屬性,因此,嚴(yán)格意義上說“C語言不能實(shí)現(xiàn)嚴(yán)格的繼承”。
3.2 用C語言實(shí)現(xiàn)繼承
在前面一節(jié)中指出“C語言不能實(shí)現(xiàn)嚴(yán)格的繼承”,盡管如此,由于繼承在軟件設(shè)計(jì)中時(shí)有使用,因此用C語言實(shí)現(xiàn)繼承仍是必要的。盡管繼承實(shí)現(xiàn)的效果不如C++等面向?qū)ο笳Z言那么完美,但還是可以達(dá)到實(shí)用程度的。
以圖1為例,Human為父類,Chinese為基類。Human類的實(shí)現(xiàn)請參考程序清單1,Chinese類的實(shí)現(xiàn)(chinese.h)請參考程序清單2,chinese.c為chinese.h中函數(shù)聲明的實(shí)現(xiàn),本文不討論這些細(xì)節(jié)。
程序清單2 Chinese類C語言實(shí)現(xiàn)
#include "human.h"
typedef struct chinese {
human_t super;
const char *city;
} chinese_t;
#define CHINESE_TO_HUMAN(p_chinese)
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_t xiaoming, *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! "); // 調(diào)用父類方法
chinese_play_mahjong(p_laowang); // 調(diào)用子類方法
本文通過使用C語言實(shí)現(xiàn)Chinese類對(duì)Human類的繼承,討論了如何使用C語言來實(shí)現(xiàn)繼承。在C++等面向?qū)ο笳Z言中對(duì)類做了原生的支持,能夠很容易地實(shí)現(xiàn)。盡管C語言不能實(shí)現(xiàn)嚴(yán)格意義上的繼承,但是通過在一個(gè)結(jié)構(gòu)體中嵌入另一個(gè)結(jié)構(gòu)體的方式,也能達(dá)到繼承的效果,與其他面向?qū)ο笳Z言不同的是,調(diào)用父類方法時(shí)需要顯式轉(zhuǎn)型。
[1] 百度百科. 面向?qū)ο骩EB/OL].(2012-12-12)[2016-08-08]http://baike.baidu.com/link?url=6XlXEOSlrKn87S7SJv4U WSX7EjstoDVm-wJ13OAod-XUrUrnZkVg3ntPFir-Ey5c6mqObZZ OevQI6K3Ungq1Mq.
Research on the implementation of inheritance with C-language
Yang Tao
(Guangzhou Zhiyuan Electric Co., Ltd., Guangzhou 510660, China)
C-language is widely used in embedded software development. But because of some reasons of developers and application scenarios, object-oriented software development methods, design patterns and other outstanding have not made good use. Today, the rising of Internet of Things and other applications, brings new challenges to the development of embedded software, and the traditional process oriented development has been difficult to support these complex applications. Therefore, it is necessary to introduce object-oriented, design patterns and other excellent software development methods in embedded software development. Object oriented method is the foundation of modern software, and inheritance is one of the three characteristics of object-oriented. Combining with the characteristics of C-language, using C language to achieve inheritance is discussed in this paper.
C-language; object-oriented; class; inheritance
TP312
A
10.19358/j.issn.1674- 7720.2016.24.005
楊韜. 用C語言實(shí)現(xiàn)繼承的研究[J].微型機(jī)與應(yīng)用,2016,35(24):16-18.
2016-09-15)
楊韜(1986-),男,學(xué)士,工程師,主要研究方向:嵌入式系統(tǒng)、軟件工程、軟件方法。