C语言利用 void 类型指针实现面向对象类概念与抽象
不使用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
C语言利用 void 类型指针实现面向对象类概念与抽象的更多相关文章
- C语言利用 void 类型指针实现面向对象类概念与抽象。
不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...
- C语言-(void*)类型指针
(void*)类型指针:ANSI新增的:即定义了一个指针,但不指定指向任何类型(即指向抽象的数据类型). 1 通过强制类型转换可将其值赋给另一指针变量 2.1用于动态存储函数的返回型指针 void m ...
- C语言之void类型及void指针 分类: C/C++ 2015-07-13 11:24 8人阅读 评论(0) 收藏
原文网址:http://www.cnblogs.com/pengyingh/articles/2407267.html 1.概述 许多初学者对C/C 语言中的void及void指针类型不甚理解,因此在 ...
- void类型指针的基本用法
void作为指针时可以用任意类型的的指针值都可以给它进行赋值和传递,但是输出时必须时显性输出 代码如下: #include<cstdio> #include<iostream> ...
- Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针
Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针 1.1. java方法引用(Method References) 与c#委托与脚本语言js ...
- void类型及void指针
1.概述 许多初学者对C/C 语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并 详述void及void指针类型的使用方法与技巧. 2 ...
- void*类型的指针
void*是一种特殊的指针类型,可以用来存放任意对象的地址.一个void*指针存放着一个地址,这一点和其他指针类似.不同的是,我们对它到底储存的是什么对象的地址并不了解: 比如:double a=2. ...
- C语言 详解多级指针与指针类型的关系
//V推论①:指针变量的步长只与‘指针变量的值’的类型有关(指针的值的类型 == 指针指向数据的类型) //指针类型跟指针的值有关,指针是占据4个字节大小的内存空间,但是指针的类型却是各不相同的 // ...
- void类型及void指针(转载)
转载 https://www.cnblogs.com/pengyingh/articles/2407267.html 2.void的含义 void的字面意思是“无类型”,void *则为“无类型指针” ...
随机推荐
- Android--ViewPager-Fragment
package com.cnn.viewpager02; import java.util.ArrayList; import java.util.List; import android.os.Bu ...
- 基于python3-sklearn,Flask 的回归预测系统
看到一副图片挺有意思,放在片头 序 "傍晚小街路面上沁出微雨后的湿润,和煦的西风吹来,抬头看看天边的晚霞,嗯明天又是一个好天气.走到水果摊旁,挑了个根蒂蜷缩.敲起来声音浊响的青绿西瓜,一边满 ...
- Golang 在 Mac、Linux、Windows 下交叉编译
Golang 支持在一个平台下生成另一个平台可执行程序的交叉编译功能. Mac下编译Linux, Windows平台的64位可执行程序: CGO_ENABLED= GOOS=linux GOARCH= ...
- sql点滴
http://www.cnblogs.com/tylerdonet/p/5509398.html
- python实例
先来一段代码: #这段代码可牛逼了,1.可以根据indent的选项调整模式.2.根据level调整级别. #代码很low,主要看思想..哈哈哈..看看从最初的样子到最好经历了什么.. 开始: #!/u ...
- Passpoint R1
Passpoint R1 自从 Android 6.0 支持从网络下载包含配置文件和凭据信息的特殊文件来配置 Passpoint R1(第 1 版)凭据,Android 就一直支持 Passpoint ...
- twig 模板引擎使渲染视图更加优雅
在使用 laravel 的时候接触过 blade 模板引擎.在学习的时候,接触到了另外一个强大的模板引擎:twig 官网:https://twig.sensiolabs.org/ 中文手册:http: ...
- php八大设计模式之观察者模式
例如在登录时,需要判断用户是第几次登录,登录过于频繁我们就给用户提示异常.根据用户的爱好,在用户登录后给予相应的猜你喜欢.如果都在 登录时判断密码的方法内完成,不符合面向对对象的单一职责.那我们该怎么 ...
- LightOJ-1341 Aladdin and the Flying Carpet 分解质因数(注意对大素数的优化)
题目链接:https://cn.vjudge.net/problem/LightOJ-1341 题意 给出一个长方形的面积a 让你算整数边长的可能取值,并且两个边都大于给定数字b 思路 唯一分解定理: ...
- HAOI树上染色
Description : 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后, ...