• 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
    ", 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
    ",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("
    Frist List length:%d
    
    ", list->length);
        printf("Head String: %s 
    
    ",(char *) list->shift(list));
        printf("End String: %s 
    
    ", list->pop(list));
        printf("List length:%d
    ", list->length);
    
        list->destroy(list);
    
        getchar();
        return 0;
    }
    复制代码

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

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

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

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

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

  • 相关阅读:
    字体大小(几号-几磅
    基于有限差分的偏移方法与基于相移方法的区别
    ubuntu aptget install problem
    su安装
    石油、天然气、地质类投稿刊物及邮箱
    ubuntu添加中文输入法
    C#使用Quartz.NET详细讲解
    Using Developer Dashboard in SharePoint 2010
    Windows Server AppFabric 使用
    列出联接和投影
  • 原文地址:https://www.cnblogs.com/findumars/p/9278593.html
Copyright © 2020-2023  润新知