c语言使用node类型指针,C语言利用 void 类型指针实现面向对象类概念与抽象

不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象。

不过多态和继承这种实现,就有点小麻烦,但是依然可以实现。

核心:

利用 void 类型指针,可以指向任意类型指针。

67d0865f17d9be527254bf8a8ff6c5b4.gif

1 //基本代码

2 void* p;

3 p = (void*) "HelloWorld";

4

5 char* str;

6 str = (char*) p;

7

8 printf("%s",str);//输出 HellWord

67d0865f17d9be527254bf8a8ff6c5b4.gif

通过这个我们就可以实现抽象性,让数据结构或函数不再与特定的类型高耦合。

从而像C++模板一样,处理任何类型元素。

面向对象的类概念:

类自身会有一组属性和一组公开或私有的方法函数,外界可以实例化一个,从而创建一个类的对象。

这在C语言里面,可以通过 struct 关键字来定义类似于类的概念结构。

我们现在来实现一组抽象的面向对象类的列表容器(List),可以装载任意对象指针:

67d0865f17d9be527254bf8a8ff6c5b4.gif

#include

#include

#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;

}

67d0865f17d9be527254bf8a8ff6c5b4.gif

这样我们就创建了解耦的通用列表容器。init相当于构造函数,destroy相当于析构函数。

仔细观察代码,编程list->xxx 即可以使用所有本身的公开函数,只是初始化的时候需要使用一下init函数。

然后我们每次将第一个参数作为自身传递,即可以像Python面向对象一样(虽然它自动传递),实现面向对象的类。

当然了,面向对象不止包括类,还有多态,抽象,接口,继承等等一系列行为,这些在C语言实现略为麻烦。

http://www.cnblogs.com/suwings/p/6500571.html

C语言利用 void 类型指针实现面向对象类概念与抽象。

不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...

C语言-&lpar;void&ast;&rpar;类型指针

(void*)类型指针:ANSI新增的:即定义了一个指针,但不指定指向任何类型(即指向抽象的数据类型). 1 通过强制类型转换可将其值赋给另一指针变量 2.1用于动态存储函数的返回型指针 void m ...

void类型指针的基本用法

void作为指针时可以用任意类型的的指针值都可以给它进行赋值和传递,但是输出时必须时显性输出 代码如下: #include #include ...

Atitit java方法引用&lpar;Method References&rpar;&&num;160&semi;与c&num;委托与脚本语言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&ast;类型的指针

void*是一种特殊的指针类型,可以用来存放任意对象的地址.一个void*指针存放着一个地址,这一点和其他指针类似.不同的是,我们对它到底储存的是什么对象的地址并不了解: 比如:double a=2. ...

C语言 详解多级指针与指针类型的关系

//V推论①:指针变量的步长只与‘指针变量的值’的类型有关(指针的值的类型 == 指针指向数据的类型) //指针类型跟指针的值有关,指针是占据4个字节大小的内存空间,但是指针的类型却是各不相同的 // ...

void类型及void指针(转载)

转载 https://www.cnblogs.com/pengyingh/articles/2407267.html 2.void的含义 void的字面意思是“无类型”,void *则为“无类型指针” ...

随机推荐

前端优化之图片延迟加载(lazyload&period;js)

要想缩短首屏加载时间,思路一般是减少http请求次数和降低每次的请求量.本文中使用现成的lazyload.js插件,文末会放出下载地址. lazyload.js可以实现图片分批次加载,不是一次性加载完 ...

Android 线程的正确使用姿势

进程优先级(Process Priority) 线程寄宿在进程当中,线程的生命周期直接被进程所影响,而进程的存活又和其优先级直接相关.在处理进程优先级的时候,大部分人靠直觉都能知道前台进程(Foreg ...

Python&period;resource-for-python-from-internet

1. pyvideo Python related video indexed so you can find it. http://pyvideo.org/ 2. 6 Useful Python L ...

POJ3680&lowbar;Intervals

给你若干个区间,每个区间有一个权值,你可以选出某些区间,使得在保证没有任何一段的覆盖次数超过k的前提下,总的权值最大. 这个建模真的十分神奇,赞一个. 对于给出的每一个区间,离散化,最终我们可以知道所 ...

第四十一课:CSS3 animation详解

animation是css3的另一个重要的模块,它成型比transition晚,吸取了Flash的关键帧的理念,实用性高. animation是一个复合样式,它可以细分为8个更细的样式. (1)ani ...

ubuntu 下串口调试工具 minicom安装与配置cutecom安装

安装minicom:     $sudo apt-get install minicom 配置minicom:    如果您的系统的默认语言不是英文,请执行下面的命令:     $LANG=EN    ...

oracle之检查点(Checkpoint)

检查点是一个数据库事件,它把修改数据从高速缓存写入磁盘,并更新控制文件和数据文件.检查点分为三类:1)局部检查点:单个实例执行数据库所有数据文件的一个检查点操作,属于此实例的全部脏缓存区写入数据文件. ...

dotnetcore 自动迁移工具

费心思做了一个简单的dotnetcore迁移工具,欢迎大家使用和交流 工具所做的工作: 查找所有输入目录的子目录和上级目录,获取包含*.sln的项目集合,可批量迁移. 替换*.sln文件中的*.csp ...

量化交易之下单函数和context对象

一.下单函数 聚宽设计的函数(如前文所说准确叫法是API)的用法都写在API文档里,位置在聚宽网站导航栏-帮助-API文档 1.order按股数下单 order(security, amount, s ...

MySQL 中的数字类型

MySQL 中数据类型常用的就三大类: 数字类型/numeric types 日期和时间/date and time types 字符类型/string (character and byte) ty ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值