C语言利用 void 类型指针实现面向对象类概念与抽象。
不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象。
不过多态和继承这种实现,就有点小麻烦,但是依然可以实现。
核心:
利用 void 类型指针,可以指向任意类型指针。
//基本代码
void* p;
p = (void*) "HelloWorld"; char* str;
str = (char*) p; 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 <= )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 <= )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 = ;
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 *));
list->push(list,(void *));
list->push(list,(void *)(char *) malloc(sizeof(char)*));
list->push(list,(void *)"wc");
list->push(list,(void *)(char *) malloc(sizeof(char)*));
list->push(list,(void *)(char *) malloc(sizeof(char)*));
list->push(list,(void *)(char *) malloc(sizeof(char)*));
list->push(list,(void *)(Book *) malloc(sizeof(Book)*));
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 ;
}
这样我们就创建了解耦的通用列表容器。init相当于构造函数,destroy相当于析构函数。
仔细观察代码,编程list->xxx 即可以使用所有本身的公开函数,只是初始化的时候需要使用一下init函数。
然后我们每次将第一个参数作为自身传递,即可以像Python面向对象一样(虽然它自动传递),实现面向对象的类。
当然了,面向对象不止包括类,还有多态,抽象,接口,继承等等一系列行为,这些在C语言实现略为麻烦。
感谢耐心阅读。
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 *则为“无类型指针” ...
随机推荐
- $("input[name=name]").val(); 无法获取值问题
<input type="text" class="text" name="name" placeholder= 例如:上海" ...
- spring data jpa 的简单使用
先说简单一下JPA 概念:JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据. 影响 ...
- Go 语言中的 Http 路由基础
最近在写一些 Go 语言的 Web 应用,因为 Go 语言中的 Web 应用和 Python 中的不太一样,具体的区别应该和语言的动态性是有所联系的,同时,也和语言的内置库支持有所联系,所以这就导致了 ...
- BZOJ3451:Tyvj1953 Normal
根据期望的线性性,答案就是 \(\sum\) 每个连通块出现次数的期望 而每个连通块次数的期望就是 \(\sum\) 连通块的根与每个点连通次数的期望 也就是对于一条路径 \((i,j)\),设 \( ...
- js中list 和 map还有string的部分操作
1.创建list或者数组 var list = []; list中添加元素:list.push("hello"); 如果没有先定义为数组类型不能使用 push方法 判断list ...
- ArcEngine对Blob字段赋值的方法
今天在测试数据入库程序,发现对某个图层操作之后,调用StopOperation,会出现“尝试写入或读取受保护的内存”错误. 经过测试,最终发现是因为该图层包含有Blob字段,而代码没有专门对Blob字 ...
- OpenGL学习--03--矩阵
Model--View--Projection 1.tutorial03.cpp // Include standard headers #include <stdio.h> #inclu ...
- Transformation functionality for the String class
String类的转换功能: package com.itheima_05; /* * String类的转换功能: * char[] toCharArray():把字符串转换为字符数组 * String ...
- JSON学习笔记-3
JSON 对象 1.对象语法 JSON 对象使用在大括号({})中书写. 对象可以包含多个 key/value(键/值)对. key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串 ...
- spring多线程初探
6月14号 晴 最高温度37 今天很热的一天啊,开发的任务现在正在测试阶段,手头没有什么工作任务,忙里偷闲,丰富一下我的blog. 前两天有个需求:调用第三方接口,这个接口的响应时间有点长,需 ...