C 語(yǔ)言實(shí)現(xiàn)繼承以及容器
掃描二維碼
隨時(shí)隨地手機(jī)看文章
筆者能力有限,寫(xiě)公眾號(hào)的目的主要是為了積累,同時(shí)也能夠激勵(lì)自己養(yǎng)成積累的習(xí)慣。如果文中有不對(duì)的地方,還請(qǐng)各位朋友能及時(shí)地給我指出來(lái),我將不勝感激,謝謝。
繼承的概念
繼承是面向?qū)ο筌浖夹g(shù)當(dāng)中的一個(gè)概念,與多態(tài)、封裝共為面向?qū)ο蟮娜齻€(gè)基本特征。繼承可以使得子類具有父類的屬性和方法或者重新定義,追加屬性和方法。面向?qū)ο笾械闹匾拍罹褪穷?,在我們熟知的編程語(yǔ)言 C++ 、Python 中都存在類的概念,通過(guò)現(xiàn)有的類從而繼承得到新的類。但是對(duì)于 C 語(yǔ)言來(lái)講,其中并不存在類的概念,那又如何實(shí)現(xiàn)繼承呢 ?
C 語(yǔ)言繼承的實(shí)現(xiàn)
筆者了解到 C 語(yǔ)言實(shí)現(xiàn)繼承是在閱讀 rt-thread 源碼中發(fā)現(xiàn)的,rt-thread 以小而美的物聯(lián)網(wǎng)操作系統(tǒng)著稱,在閱讀其源碼的時(shí)候,也能夠感受到其實(shí)現(xiàn)的精妙,其中對(duì)于內(nèi)核對(duì)象的管理就是以面向?qū)ο蟮姆绞竭M(jìn)行,采用結(jié)構(gòu)體嵌套的方式實(shí)現(xiàn)了內(nèi)核對(duì)象的繼承與派生。在 rt-thread 的內(nèi)核對(duì)象管理模塊中,定義了通用的數(shù)據(jù)結(jié)構(gòu) rtobject ,筆者在這里姑且將其稱之為父類,因?yàn)閮?nèi)核的線程對(duì)象,內(nèi)存池對(duì)象,定時(shí)器對(duì)象,設(shè)備對(duì)象都是由 rtobject 派生而來(lái)。下面是 rt_object 的實(shí)現(xiàn)細(xì)節(jié)。
struct rt_object
{
char name[RT_NAME_MAX]; /**< name of kernel object */
rt_uint8_t type; /**< type of kernel object */
rt_uint8_t flag; /**< flag of kernel object */
rt_list_t list; /**< list node of kernel object */
};
有了這個(gè)通用數(shù)據(jù)結(jié)構(gòu),我們就可以依據(jù)此繼承派生出新的內(nèi)核對(duì)象,比如定時(shí)器對(duì)象,其實(shí)現(xiàn)細(xì)節(jié)如下所示:
struct rt_timer
{
struct rt_object parent; /**< inherit from rt_object */
rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];
void (*timeout_func)(void *parameter); /**< timeout function */
void *parameter; /**< timeout function's parameter */
rt_tick_t init_tick; /**< timer timeout tick */
rt_tick_t timeout_tick; /**< timeout tick */
};
如上圖代碼所示,rttimer 結(jié)構(gòu)體內(nèi)定義的 parent 就是由 rtobject 所繼承下來(lái)的,在繼承的基礎(chǔ)上,又在結(jié)構(gòu)體內(nèi)增加了新的內(nèi)容,從而形成了定時(shí)器對(duì)象。因此對(duì)于 rt_thread 中的線程對(duì)象,內(nèi)存池對(duì)象,定時(shí)器對(duì)象也可以用如下的一張圖表明他們之間的關(guān)系。
上述就是關(guān)于繼承的概念及 C 語(yǔ)言的具體的實(shí)現(xiàn)方式。
容器的概念
在 C++ 中對(duì)于容器的定義是這樣的:在數(shù)據(jù)存儲(chǔ)上,有一種對(duì)象類型,它可以持有其他對(duì)象或者指向其他對(duì)象的指針,這種對(duì)象類型就是容器,對(duì)于 C++ 來(lái)說(shuō),有專門的構(gòu)造函數(shù)實(shí)現(xiàn)容器,比如 vector() ,就可以創(chuàng)建一個(gè)容器。那 C 語(yǔ)言是如何創(chuàng)建一個(gè)容器呢 ?在 rtthread 中,是通過(guò)一個(gè)全局?jǐn)?shù)組的形式實(shí)現(xiàn)的,數(shù)組的類型是 rtobjectinformation ,rtobject_information 的實(shí)現(xiàn)代碼如下:
struct rt_object_information
{
enum rt_object_class_type type; /**< object class type */
rt_list_t object_list; /**< object list */
rt_size_t object_size; /**< object size */
};
其中,type 是用一個(gè)枚舉類型實(shí)現(xiàn)的,具體實(shí)現(xiàn)如下:
enum rt_object_info_type
{
RT_Object_Info_Thread = 0, /**< The object is a thread. */
#ifdef RT_USING_SEMAPHORE
RT_Object_Info_Semaphore, /**< The object is a semaphore. */
#endif
#ifdef RT_USING_MUTEX
RT_Object_Info_Mutex, /**< The object is a mutex. */
#endif
RT_Object_Info_Unknown, /**< The object is unknown. */
};
對(duì)象的鏈表是基于這樣實(shí)現(xiàn)的:
struct rt_list_node
{
struct rt_list_node *next; /**< point to next node. */
struct rt_list_node *prev; /**< point to prev node. */
};
由于 rt_thread 中容器中的對(duì)象有點(diǎn)多,筆者將其中對(duì)象進(jìn)行縮減,截取一部分出來(lái),具體如下:
static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
{
/* initialize object container - thread */
{
RT_Object_Class_Thread,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread),
sizeof(struct rt_thread)
},
#ifdef RT_USING_SEMAPHORE
/* initialize object container - semaphore */
{
RT_Object_Class_Semaphore,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore),
sizeof(struct rt_semaphore)
},
#endif
#ifdef RT_USING_MUTEX
/* initialize object container - mutex */
{
RT_Object_Class_Mutex,
_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex),
sizeof(struct rt_mutex)
},
#endif
}
上面就實(shí)現(xiàn)了一個(gè)容器,其中OBJCONTAINERLISTINIT 是一個(gè)宏定義,具體定義如下:
#define _OBJ_CONTAINER_LIST_INIT(c) \
{&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
其所用是初始化對(duì)象的鏈表,將頭尾指針都指向自身,實(shí)現(xiàn)的效果如下: 所以總體來(lái)說(shuō),rt_thread 中實(shí)現(xiàn)的容器里的內(nèi)容就包含每一個(gè)內(nèi)核對(duì)象,然后內(nèi)核對(duì)象是由一個(gè)結(jié)構(gòu)體實(shí)現(xiàn)的,結(jié)構(gòu)體包含著內(nèi)核對(duì)象的類型,初始化好的內(nèi)核對(duì)象鏈表以及內(nèi)核對(duì)象的大小。既然如此我們就可以對(duì)容器里的內(nèi)容進(jìn)行操作,比如獲得指定內(nèi)核對(duì)象的指針,代碼如下:
rt_object_get_information(enum rt_object_class_type type)
{
int index;
for (index = 0; index < RT_Object_Info_Unknown; index ++)
if (rt_object_container[index].type == type)
return &rt_object_container[index];
return RT_NULL;
}
總結(jié)
通過(guò) C 語(yǔ)言實(shí)現(xiàn)的繼承與派生,rt_thread 實(shí)現(xiàn)了多個(gè)內(nèi)核對(duì)象的定義,然后通過(guò) C 語(yǔ)言實(shí)現(xiàn)的容器,我們可以管理內(nèi)核對(duì)象,容器中包含的內(nèi)核對(duì)象有對(duì)象本身的鏈表,拿線程打比方,我們新創(chuàng)建的線程也就可以通過(guò)鏈表的形式掛接到容器中對(duì)應(yīng)的線程控制塊中,實(shí)現(xiàn)的效果如下:
您的建議是對(duì)我最大的提升,您的在看是對(duì)我最大的鼓勵(lì)。歡迎點(diǎn)擊下方圖片進(jìn)入小程序進(jìn)行評(píng)論
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!