前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C语言如何实现继承及容器

C语言如何实现继承及容器

原创
作者头像
wenzid
修改2020-04-26 14:24:23
2.5K0
修改2020-04-26 14:24:23
举报

继承的概念

继承是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义,追加属性和方法。

面向对象中的重要概念就是类,在我们熟知的编程语言 C++ 、Python 中都存在类的概念,通过现有的类从而继承得到新的类。但是对于 C 语言来讲,其中并不存在类的概念,那又如何实现继承呢 ?

C 语言继承的实现

笔者了解到 C 语言实现继承是在阅读 rt-thread 源码中发现的,rt-thread 以小而美的物联网操作系统著称,在阅读其源码的时候,也能够感受到其实现的精妙,其中对于内核对象的管理就是以面向对象的方式进行,采用结构体嵌套的方式实现了内核对象的继承与派生。在 rt-thread 的内核对象管理模块中,定义了通用的数据结构 rt_object ,笔者在这里姑且将其称之为父类,因为内核的线程对象,内存池对象,定时器对象,设备对象都是由 rt_object 派生而来。下面是 rt_object 的实现细节。

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 */
};

有了这个通用数据结构,我们就可以依据此继承派生出新的内核对象,比如定时器对象,其实现细节如下所示:

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 */
};

如上图代码所示,rt_timer 结构体内定义的 parent 就是由 rt_object 所继承下来的,在继承的基础上,又在结构体内增加了新的内容,从而形成了定时器对象。

因此对于 rt_thread 中的线程对象,内存池对象,定时器对象也可以用如下的一张图表明他们之间的关系。

在这里插入图片描述
在这里插入图片描述

容器的概念

在 C++ 中对于容器的定义是这样的:在数据存储上,有一种对象类型,它可以持有其他对象或者指向其他对象的指针,这种对象类型就是容器,对于 C++ 来说,有专门的构造函数实现容器,比如 vector() ,就可以创建一个容器。

那 C 语言是如何创建一个容器呢 ?在 rt_thread 中,是通过一个全局数组的形式实现的,数组的类型是 rt_object_information ,rt_object_information 的实现代码如下:

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 是用一个枚举类型实现的,具体实现如下:

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. */
};

对象的链表是基于这样实现的:

struct rt_list_node
{
    struct rt_list_node *next;                          /**< point to next node. */
    struct rt_list_node *prev;                          /**< point to prev node. */
};

由于 rt_thread 中容器中的对象有点多,笔者将其中对象进行缩减,截取一部分出来,具体如下:

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
}

上面就实现了一个容器,其中_OBJ_CONTAINER_LIST_INIT 是一个宏定义,具体定义如下:

#define _OBJ_CONTAINER_LIST_INIT(c)     \
    {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}

其所用是初始化对象的链表,将头尾指针都指向自身,实现的效果如下:

在这里插入图片描述
在这里插入图片描述
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;
}

总结

通过 C 语言实现的继承与派生,rt_thread 实现了多个内核对象的定义,然后通过 C 语言实现的容器,我们可以管理内核对象,容器中包含的内核对象有对象本身的链表,拿线程打比方,我们新创建的线程也就可以通过链表的形式挂接到容器中对应的线程控制块中,实现的效果如下:

在这里插入图片描述
在这里插入图片描述

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 继承的概念
    • C 语言继承的实现
    • 容器的概念
    • 总结
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档