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

这篇博客介绍了如何在不使用C++的情况下,利用C语言的void指针来实现面向对象的概念,包括类的属性和方法。通过定义一个结构体来模拟类,并使用void指针存储任意类型的数据,实现了类似C++中模板的功能。文中给出了一个抽象的双向链表容器(List)的例子,展示了如何创建、销毁、插入和删除元素。此外,还探讨了C语言中void指针的用途和多态性在C语言中的实现难度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

核心:

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

//基本代码

void* p;

p = (void*) "HelloWorld";

char* str;

str = (char*) p;

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

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

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

面向对象的类概念:

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

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

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

#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 <= )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++时,很多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 *则为“无类型指针” ...

随机推荐

python语言中的编码问题

在编程的过程当中,常常会遇到莫名其妙的乱码问题.很多人选择出了问题直接在网上找答案,把别人的例子照搬过来,这是快速解决问题的一个好办法.然而,作为一个严谨求实的开发者,如果不从源头上彻底理解乱码产生的 ...

人民币大写金额转换C&num;方法

方法的代码如下: /// /// 人民币大写 /// /// ...

java pdf转换jpg

/** * 把PDF所有页转换为JPG, 并返回所有图片的路劲集合 * @param inputFilePath * 图片路径,具体到文件名 * @param outputFilePath * 输出目 ...

poj3468&lpar;线段树 边覆盖&rpar;

#include int lb,rb,data; long long sum[5000000],extra[5000000]; void add(int l,int r,i ...

Eclipse使用git 上传代码至github

右击项目,选择Team->Share Project,弹出如下窗口. 选择git,next,在弹出的界面上,①先勾选Use or create……,②createrepository,③勾选工程 ...

java对象和json对象之间互相转换

import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.Li ...

03SpringBoot用JdbcTemplates访问Mysql

03SpringBoot用JdbcTemplates访问Mysql 文章指导 学习笔记 学习代码 初始化mysql -- create table `account` DROP TABLE `acco ...

Space Elevator &lbrack;POJ2392&rsqb; &lbrack;DP&rsqb;&lbrack;优化&rsqb;

题目大意 n件物品,第i件hi高,有ci件,最高的一件不能超过ai的高度.问最高能堆多高 输入: 第一行,一个n 接下来每一行,为hi,ai,ci 输出,最高堆多高 样例输入: 37 40 35 23 ...

Kotlin入门&lpar;9&rpar;函数的基本用法

上一篇文章介绍了Kotlin新增的空安全机制,控制语句部分可算是讲完了,接下来将连续描述Kotlin如何定义和调用函数,本篇文章先介绍函数的基本用法. 前面几篇文章介绍控制语句之时,在setOnCli ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值