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

2018-06-18 04:07:58来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

不使用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语言实现略为麻烦。

 

感谢耐心阅读。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:【C语言篇】? 16. 标准函数、预处理

下一篇:【C语言篇】? 15. 结构体、联合体、枚举