楊 韜
(廣州致遠(yuǎn)電子股份有限公司,廣東 廣州 510660)
?
用C語言實(shí)現(xiàn)類實(shí)例化的研究
楊 韜
(廣州致遠(yuǎn)電子股份有限公司,廣東 廣州 510660)
多年以來,C語言在嵌入式軟件開發(fā)中被廣泛使用,但由于開發(fā)人員和應(yīng)用場景等原因,面向?qū)ο?、設(shè)計模式等優(yōu)秀的軟件開發(fā)方法始終沒有很好地運(yùn)用起來。時至今日,物聯(lián)網(wǎng)等應(yīng)用的興起,給嵌入式軟件開發(fā)帶來新的挑戰(zhàn),而傳統(tǒng)的面向過程開發(fā)已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,有必要在嵌入式軟件開發(fā)中引入面向?qū)ο蟆⒃O(shè)計模式等優(yōu)秀的軟件開發(fā)方法。面向?qū)ο笫乾F(xiàn)代軟件方法的根基,面向?qū)ο篌w現(xiàn)在類上,使用類來創(chuàng)建對象的過程就是實(shí)例化。文章結(jié)合C語言的特性,對使用C語言實(shí)現(xiàn)類實(shí)例化進(jìn)行了討論。
C語言;面向?qū)ο?;類;?shí)例化
物聯(lián)網(wǎng)等應(yīng)用的興起,給嵌入式軟件開發(fā)帶來新的挑戰(zhàn),而傳統(tǒng)的面向過程開發(fā)已經(jīng)難以支撐這些復(fù)雜的應(yīng)用。因此,有必要在嵌入式軟件開發(fā)中引入面向?qū)ο蟆⒃O(shè)計模式等優(yōu)秀的軟件開發(fā)方法。本文討論了如何使用C語言來實(shí)現(xiàn)類的實(shí)例化。在C++等面向?qū)ο笳Z言中對類做了原生的支持,使用new這類關(guān)鍵字即可實(shí)例化一個對象。盡管C語言并不支持new,但是通過對實(shí)例化過程的分析和拆分,也能實(shí)現(xiàn)實(shí)例化。
1.1 類
面向?qū)ο笥蟹庋b、繼承、多態(tài)三大特性,這些特性主要通過類來體現(xiàn)。類就是一個封裝了屬性以及相關(guān)操作的代碼的邏輯實(shí)體。
類具有屬性,它是對象的狀態(tài)的抽象,用數(shù)據(jù)結(jié)構(gòu)來描述類的屬性。
類具有方法,它是對象的行為的抽象,用方法名和實(shí)現(xiàn)該操作的方法來描述。
除了封裝屬性和操作外,類還具有訪問控制的能力,比如,某些屬性和方法可以是私有的,不能被外界訪問。通過訪問控制,能夠?qū)?nèi)部數(shù)據(jù)提供不同級別的保護(hù),以防止外界意外地改變或使用了私有部分。不同的編程語言提供的訪問控制等級不盡相同,但都有公有、私有兩個等級。
類是抽象的數(shù)據(jù)類型,在內(nèi)存中并不存在(Python等動態(tài)語言除外),只有類的實(shí)例存在于內(nèi)存中。
1.2 對象
對象是人們要進(jìn)行研究的任何事物,從最簡單的整數(shù)到復(fù)雜的飛機(jī)等均可看作為對象,它不僅能表示具體的事物,還能表示抽象的規(guī)則、計劃或事件。
對象具有狀態(tài),一個對象用數(shù)據(jù)值來描述它的狀態(tài)。
對象還有操作,用于改變對象的狀態(tài),對象及其操作就是對象的行為。
對象實(shí)現(xiàn)了數(shù)據(jù)和操作的結(jié)合,使數(shù)據(jù)和操作封裝于對象的統(tǒng)一體中。
1.3 實(shí)例化
用類創(chuàng)建對象的過程就是實(shí)例化,創(chuàng)建的對象被稱為類的實(shí)例。實(shí)例化包含兩個步驟,第一步是分配對象的內(nèi)存,第二步是初始化對象的內(nèi)存。
類的第一大特性為封裝,封裝即將對象的屬性和方法封裝在一起,在C語言中可以使用.C、.H和結(jié)構(gòu)體實(shí)現(xiàn)類的封裝特性。
圖1 Human類圖
以圖1中Human類為例,可以使用human.h、human.c、struct human三個元素來完成封裝,human.c為human.h中函數(shù)聲明的實(shí)現(xiàn),本文不討論這些細(xì)節(jié),所以只給出如下human.h的關(guān)鍵代碼片段:
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);
實(shí)例化包含兩個步驟:分配對象的內(nèi)存和初始化對象的內(nèi)存。接下來本文以圖1中Human類的實(shí)例化為例,討論C語言如何實(shí)現(xiàn)類的實(shí)例化。
3.1 對象的內(nèi)存
如果把類看做類型,那么類的實(shí)例就是變量,既然是變量,那么就有動態(tài)變量、靜態(tài)變量和棧變量之分。在C語言中,使用malloc()這類動態(tài)內(nèi)存分配函數(shù)得到的變量就是動態(tài)變量;全局變量和加了static關(guān)鍵字的變量就是靜態(tài)變量;在函數(shù)內(nèi)創(chuàng)建的局部變量就是棧變量。下面的代碼展示了C語言中的這幾類變量:
#include "human.h"
struct human g_john;
/* 靜態(tài)變量 */
static struct human __g_john;
/* 靜態(tài)變量 */
void foo (void)
{
static struct human s_john;
/* 靜態(tài)變量 */
struct human john;
/* 棧變量 */
struct human *p_john = malloc(sizeof(*p_john));
/* 動態(tài)變量 */
}
站在內(nèi)存的角度,可以把類看做結(jié)構(gòu)體類型,類的實(shí)例就是結(jié)構(gòu)體變量,因此,對象也就有動態(tài)對象、靜態(tài)對象和棧對象之分,它們之間的區(qū)別如表1所示。
表1 靜態(tài)對象、動態(tài)對象和棧對象
對于嵌入式軟件中的C面向?qū)ο缶幊蹋浞掷斫獗?中的這三類對象是非常有必要的。大多數(shù)情況下,一個類都要能夠被實(shí)例化為靜態(tài)對象。
3.2 對象的初始化
初始化對象就是初始化對象的內(nèi)存,在初始化之前,必然要先得到對象的內(nèi)存(上一小節(jié)已討論),但無論對象的內(nèi)存是何種類型,初始化的操作都是相同的。在JAVA等編程語言中,完成此操作的函數(shù)被稱作構(gòu)造函數(shù),使用C語言來實(shí)現(xiàn)就是一個名為xxxx_init()的初始化函數(shù),也可稱之為構(gòu)造函數(shù)。
以Human類為例,它的初始化函數(shù)human_init()如下面的代碼所示,可留意到對象的內(nèi)存需要顯式傳遞給它。
human_t *human_init (human_t *p_this, const char *name, int money)
{
p_this->name = name;
p_this->_money = money;
return p_this;
}
3.3 實(shí)例化
前面兩小節(jié)分別討論了對象的內(nèi)存和對象的初始化,這兩步組成了實(shí)例化。下面的代碼展示了不同類型對象的實(shí)例化:
#include "human.h"
human_t g_john;
/* 靜態(tài)對象 */
static human_t __g_jen;
/* 靜態(tài)對象 */
void foo (void)
{
static human_t s_jack;
/* 靜態(tài)對象 */
human_t tom;
/* 棧對象 */
human_t*p_lee_mem= malloc(sizeof(*p_lee_mem));
/* 動態(tài)對象 */
// 實(shí)例化上面定義的靜態(tài)對象、動態(tài)對象和棧對象
human_t *p_john= human_init(&g_john, "john", 100);
human_t *p_jen = human_init(&__g_jen, "jen", 100);
human_t *p_jack = human_init(&s_jack, "jack", 100);
human_t *p_tom = human_init(&tom, "tom", 100);
human_t *p_lee = human_init(p_lee_mem, "lee", 100);
3.4 訪問對象
對象實(shí)例化后便存于內(nèi)存中,此時可以訪問對象的屬性和方法,下面的代碼展示了對象的訪問:
#include "human.h"
void foo (void)
{
human_t john;
/* 定義對象內(nèi)存 */
p_john = human_init(&jhon, "John", 100);
/* 初始化對象 */
printf("Human %s is born!", p_john->name);
/* 訪問對象的屬性 */
human_talk(p_john, "I am hungry");
/* 訪問對象的方法 */
human_deinit(&john)
/* 對象解初始化 */
}
3.5 銷毀對象
當(dāng)對象不再使用時,便可銷毀之。銷毀對象與創(chuàng)建對象(實(shí)例化)的操作相反,首先對對象進(jìn)行解初始化操作,然后再釋放對象的內(nèi)存。
以Human類為例,首先調(diào)用human_deinit()完成對象的解初始化,接下來,如果是靜態(tài)對象或棧對象就不用顯式釋放對象的內(nèi)存,因?yàn)殪o態(tài)對象或棧對象有確定的生命周期;如果是調(diào)用malloc()等函數(shù)得到了動態(tài)對象,則必須調(diào)用free()等對應(yīng)的函數(shù)釋放對象的內(nèi)存。下面的代碼展示了各種對象的銷毀:
#include "human.h"
human_t g_john;
/* 靜態(tài)對象 */
static human_t __g_jen;
/* 靜態(tài)對象 */
void foo (void)
{
static human_t s_jack;
/* 靜態(tài)對象 */
human_t tom;
/* 棧對象 */
human_t*p_lee_mem= malloc(sizeof(*p_lee_mem));
/* 動態(tài)對象 */
// 實(shí)例化上面定義的靜態(tài)對象、動態(tài)對象和棧對象
human_t *p_john = human_init(&g_john, "john", 100);
human_t *p_jen = human_init(&__g_jen, "jen", 100);
human_t *p_jack = human_init(&s_jack, "jack", 100);
human_t *p_tom = human_init(&tom, "tom", 100);
human_t *p_lee = human_init(p_lee_mem, "lee", 100);
/* 銷毀對象 */
human_deinit(p_john);
human_deinit(p_jen);
human_deinit(p_jack);
human_deinit(p_tom);
human_deinit(p_lee);
free(p_lee_mem);
/* 注意:需要用戶釋放動態(tài)申請的對象內(nèi)存 */
}
本文通過使用C語言實(shí)現(xiàn)Human類的實(shí)例化,討論了如何使用C語言來實(shí)現(xiàn)類的實(shí)例化。在C++等面向?qū)ο笳Z言中對類做了原生的支持,使用new這類關(guān)鍵字即可實(shí)例化一個對象。盡管C語言并不支持new,但是通過對實(shí)例化過程的分析和拆分,也能實(shí)現(xiàn)實(shí)例化。
[1] 百度. 百度百科/面向?qū)ο骩EB/OL].(2016-08-08).http://baike.baidu.com/link?url=6XlXEOSlrKn87S7SJv4 UWSX7EjstoDVm-wJ13OAod-XUrUrnZkVg3ntPFir-Ey5c6mqOb ZZOevQI6K3Ungq1Mq.
Research on the implementation of class instantiation with C-language
Yang Tao
(Guangzhou Zhiyuan Electric Co. Ltd. , Guangzhou 510660, China)
Over the years, C-language is widely used in embedded software development, but because of developers and application scenarios and other reasons, object-oriented, design patterns and other outstanding software development methods have not been well used. Today, the rise of Internet of Things and other applications, has brought 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, object-oriented is embodied in the class. The process of using the class to create the object is instantiation. Combining with the characteristics of C language, the implementation of class instantiation by using C language is discussed.
C-language; object-oriented; class; instantiation
TP312
A
10.19358/j.issn.1674- 7720.2016.23.004
楊韜. 用C語言實(shí)現(xiàn)類實(shí)例化的研究[J].微型機(jī)與應(yīng)用,2016,35(23):15-17.
2016-09-20)
楊韜(1986-),男,學(xué)士,工程師,主要研究方向:嵌入式系統(tǒng)、軟件工程、軟件方法。