不使用C++時,不少C語言新手可能認爲C語言缺少了面向對象和抽象性,事實上,C語言經過某種組合方式,能夠間接性的實現面對對象和抽象。node
不過多態和繼承這種實現,就有點小麻煩,可是依然能夠實現。編程
利用 void 類型指針,能夠指向任意類型指針。數據結構
1 //基本代碼
2 void* p; 3 p = (void*) "HelloWorld"; 4
5 char* str; 6 str = (char*) p; 7
8 printf("%s",str);//輸出 HellWord
經過這個咱們就能夠實現抽象性,讓數據結構或函數再也不與特定的類型高耦合。函數
從而像C++模板同樣,處理任何類型元素。測試
類自身會有一組屬性和一組公開或私有的方法函數,外界能夠實例化一個,從而建立一個類的對象。spa
這在C語言裏面,能夠經過 struct 關鍵字來定義相似於類的概念結構。指針
#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\n", 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\n",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("\nFrist List length:%d\n\n", list->length); printf("Head String: %s \n\n",(char *) list->shift(list)); printf("End String: %s \n\n", list->pop(list)); printf("List length:%d\n", list->length); list->destroy(list); getchar(); return 0; }
這樣咱們就建立了解耦的通用列表容器。init至關於構造函數,destroy至關於析構函數。code
仔細觀察代碼,編程list->xxx 便可以使用全部自己的公開函數,只是初始化的時候須要使用一下init函數。對象
而後咱們每次將第一個參數做爲自身傳遞,便可以像Python面向對象同樣(雖然它自動傳遞),實現面向對象的類。blog
固然了,面向對象不止包括類,還有多態,抽象,接口,繼承等等一系列行爲,這些在C語言實現略爲麻煩。
感謝耐心閱讀。