不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象。
不过多态和继承这种实现,就有点小麻烦,但是依然可以实现。
核心:
利用 void 类型指针,可以指向任意类型指针。
1 //基本代码 2 void* p; 3 p = (void*) "HelloWorld"; 4 5 char* str; 6 str = (char*) p; 7 8 printf("%s",str);//输出 HellWord
通过这个我们就可以实现抽象性,让数据结构或函数不再与特定的类型高耦合。
从而像C++模板一样,处理任何类型元素。
面向对象的类概念:
类自身会有一组属性和一组公开或私有的方法函数,外界可以实例化一个,从而创建一个类的对象。
这在C语言里面,可以通过 struct 关键字来定义类似于类的概念结构。
我们现在来实现一组抽象的面向对象类的列表容器(List),可以装载任意对象指针:
#include <stdio.h> #include <stdlib.h> #define SIEZ_NAME 200 #define Class struct //双向链表 typedef Class Struct_List_Node{ void * item; struct Struct_List_Node * next; struct Struct_List_Node * previous; }WList_Node; typedef Class Struct_WList{ //类的属性 WList_Node* head; WList_Node* end; int length; //公开方法函数 void (*push)(Class Struct_WList*,void*); void (*destroy)(Class Struct_WList* ); void* (*pop)(Class Struct_WList* ); void* (*shift)(Class Struct_WList* ); }WList; void WList_push(WList* self,void* item){ WList_Node* new_node = (WList_Node* )malloc(sizeof(WList_Node)); new_node->item = item; new_node->next = NULL; new_node->previous = NULL; printf("Push %p ", new_node); self->length++; if(self->head == NULL){ self->head = self->end = new_node; }else{ new_node->previous = self->end; self->end = self->end->next = new_node; } } void* WList_pop(WList* self){ if(self->length <= 0 )return NULL; WList_Node* pop_node; self->length--; pop_node = self->end; pop_node->previous->next = NULL; void* return_p = pop_node->item; free(pop_node); return return_p; } void* WList_shift(WList* self){ if(self->length <= 0 )return NULL; WList_Node* pop_node; self->length--; pop_node = self->head; self->head = self->head->next; self->head->previous = NULL; void* return_p = pop_node->item; free(pop_node); return return_p; } void WList_destroy(WList* self){ WList_Node* destroy_node; while(self->head){ destroy_node = self->head; self->head = self->head->next; printf("WList_destroy: %p ",destroy_node); free(destroy_node); } } void WList_init(WList* self){ self->length = 0; self->head = self->end = NULL; self->push = WList_push; self->pop = WList_pop; self->shift = WList_shift; self->destroy = WList_destroy; } //测试类型 typedef Class struct_book{ char name[SIEZ_NAME]; int price; }Book; int main(){ //测试 WList* list = (WList*) malloc(sizeof(WList)); WList_init(list); list->push(list,"Head !");//C可以省略强制转换,但不建议 list->push(list,(void *)'S'); list->push(list,(void *)66666); list->push(list,(void *)2); list->push(list,(void *)(char *) malloc(sizeof(char)*10)); list->push(list,(void *)"wc"); list->push(list,(void *)(char *) malloc(sizeof(char)*10)); list->push(list,(void *)(char *) malloc(sizeof(char)*52)); list->push(list,(void *)(char *) malloc(sizeof(char)*100)); list->push(list,(void *)(Book *) malloc(sizeof(Book)*10)); list->push(list,(void *)"HelloWorld!!!!"); printf(" Frist List length:%d ", list->length); printf("Head String: %s ",(char *) list->shift(list)); printf("End String: %s ", list->pop(list)); printf("List length:%d ", list->length); list->destroy(list); getchar(); return 0; }
这样我们就创建了解耦的通用列表容器。init相当于构造函数,destroy相当于析构函数。
仔细观察代码,编程list->xxx 即可以使用所有本身的公开函数,只是初始化的时候需要使用一下init函数。
然后我们每次将第一个参数作为自身传递,即可以像Python面向对象一样(虽然它自动传递),实现面向对象的类。
当然了,面向对象不止包括类,还有多态,抽象,接口,继承等等一系列行为,这些在C语言实现略为麻烦。
http://www.cnblogs.com/suwings/p/6500571.html