C语言利用 void 类型指针实现面向对象类概念与抽象
2024-10-01 18:10:40
不使用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\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相当于析构函数。
仔细观察代码,编程list->xxx 即可以使用所有本身的公开函数,只是初始化的时候需要使用一下init函数。
然后我们每次将第一个参数作为自身传递,即可以像Python面向对象一样(虽然它自动传递),实现面向对象的类。
当然了,面向对象不止包括类,还有多态,抽象,接口,继承等等一系列行为,这些在C语言实现略为麻烦。
http://www.cnblogs.com/suwings/p/6500571.html
最新文章
- java (基本语法)
- Java基础-基本数据类型转换案例
- 面向对象编程(十二)——final关键字
- 【重走Android之路】【开篇】序
- 关于GC进行垃圾回收的时机
- sts 去掉启动的rss功能
- PHPExcel 生成图形报表
- web中纯java获取配置文件中的数据
- .NET中数据访问方式(一):LINQ
- 想要写出高性能sql语句,你得记住这些……
- Hibernate之深入Hibernate的映射文件
- spring+mybaits多数据源使用
- C#写入Oracle 中文乱码问题
- 重建控制文件ORA-12720
- SurfaceView+MediaPlayer播放视频
- supervisor Error: Another program is already listening
- c#:判断一个数组元素中否有重复元素
- .NET Socket 简单入门
- 惭愧, eclipse 之 build path
- How to detect whether socket is still connected...