/** *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语言面向对象的实现---多态性》
有疑问加站长微信联系(非本文作者)