模仿go语言的C语言面向对象范式

bbeikke · · 1652 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

/**
*C语言模拟go语言对多态的实现
*定义一个接口,一个类实现了该接口的所有函数,
*则这个类即为该接口的实现,不显式声明一个类实现的接口
*
*在C语言中,则定义一个包含一组函数指针的结构体模拟接口
*子类有一个创建该结构体的函数,则表示该子类实现接口
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifndef SAFE_FREE
#define SAFE_FREE(p) \
do \
{ \
    free(p); \
    p = NULL; \
} while (0)
#endif //SAFE_FREE

/**
*定义接口
*cthis是一个指针,指向实现该接口的类
*eat是接口包含的函数(函数指针)
*/
typedef struct _i_animal
{
    void *cthis;
    void (*eat)(void *cthis);
} i_animal;

/**
*数据类型rabbit
*含有一个属性name
*/
typedef struct _rabbit
{
    char *name;
} rabbit;

/**
*rabbit实现i_animal接口需要的函数
*/
void rabbit_eat(void *cthis)
{
    printf("%s eat!\n", ((rabbit*)cthis)->name);
}

/**
*表示rabbit实现了i_animal接口
*该函数返回rabbit对接口i_animal的实现
*/
i_animal *rabbit_i_animal(void *cthis)
{
    i_animal *instance = (i_animal*)malloc(sizeof(i_animal));
    if (NULL == instance)
    {
        return NULL;
    }
    memset(instance, 0, sizeof(i_animal));
    instance->cthis = cthis;
    instance->eat = rabbit_eat;
    return instance;
}

/**
*rabbit的构造函数
*/
rabbit *rabbit_create(void)
{
    int nameLength = 10;
    rabbit *instance = (rabbit*)malloc(sizeof(rabbit));
    if (NULL == instance)
    {
        return NULL;
    }
    memset(instance, 0, sizeof(rabbit));
    instance->name = (char*)malloc(nameLength*sizeof(char));
    if (NULL != instance->name)
    {
        memset(instance->name, 0, nameLength*sizeof(char));
        strcpy(instance->name, "rabbit");
    }
    return instance;
}

/**
*rabbit的析构函数
*/
void rabbit_release(rabbit *cthis)
{
    SAFE_FREE(cthis->name);
    SAFE_FREE(cthis);
}

/**
*数据类型cat
*含有一个属性name
*/
typedef struct 
{
    char *name;
} cat;

/**
*cat实现i_animal接口需要的函数
*/
void cat_eat(void *cthis)
{
    printf("%s eat!\n", ((cat*)cthis)->name);
}

/**
*表示cat实现了i_animal接口
*该函数返回cat对接口i_animal的实现
*/
i_animal *cat_i_animal(void *cthis)
{
    i_animal *instance = (i_animal*)malloc(sizeof(i_animal));
    if (NULL == instance)
    {
        return NULL;
    }
    memset(instance, 0, sizeof(i_animal));
    instance->cthis = cthis;
    instance->eat = cat_eat;
    return instance;
}

/**
*cat的构造函数
*/
cat *cat_create(void)
{
    int nameLength = 10;
    cat *instance = (cat*)malloc(sizeof(cat));
    if (NULL == instance)
    {
        return NULL;
    }
    memset(instance, 0, sizeof(cat));
    instance->name = (char*)malloc(nameLength*sizeof(char));
    if (NULL != instance->name)
    {
        memset(instance->name, 0, nameLength*sizeof(char));
        strcpy(instance->name, "cat");
    }
    return instance;
}

/**
*cat的析构函数
*/
void cat_release(cat *cthis)
{
    SAFE_FREE(cthis->name);
    SAFE_FREE(cthis);
}

/**
*主函数
*/
int main()
{
    // 用于循环遍历的变量
    int i = 0;
    // 数组的长度
    int animals_length = 2;

    // 创建rabbit实例
    rabbit *rabbit_instance = rabbit_create();
    // 创建cat实例
    cat *cat_instance = cat_create();

    // 保存接口实现的数组 
    i_animal *animals[2] = {NULL};

    // 创建rabbit对接口i_animal的实现
    animals[0] = rabbit_i_animal(rabbit_instance);
    // 创建cat对接口i_animal的实现
    animals[1] = cat_i_animal(cat_instance);

    // 模拟多态
    for (i = 0; i < animals_length; ++i)
    {
        // 空指针判断
        if (NULL == animals[i])
        {
            continue;
        }
        // 同一段代码,不同绑定,结果会不同
        animals[i]->eat(animals[i]->cthis);
        // 接口由子类对应函数创建,需要手动释放
        SAFE_FREE(animals[i]);
    }

    // 析构rabbit
    rabbit_release(rabbit_instance);
    // 析构cat
    cat_release(cat_instance);
    return 0;
}


参考:

1、《我所偏爱的C语言面向对象编程范式》 云风的 BLOG

2、《Go语言初步》 云风的 BLOG

3、《俺使用的C语言面向对象范式

4、《Go For C++ Programmers(C++程序员指南)

5、《OO in C(1): C语言中的类模拟和多态,继承

6、《C语言面向对象的实现---多态性


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:bbeikke

查看原文:模仿go语言的C语言面向对象范式

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1652 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传