美文网首页C
C 迷你系列(五)不透明指针

C 迷你系列(五)不透明指针

作者: Tubetrue01 | 来源:发表于2021-02-10 08:14 被阅读0次

    不透明指针

    C 不支持面向对象编程,不过,借助不透明指针,我们也可以使用 C 封装数据以及支持某种程度的多态行为。我们可以隐藏数据结构的实现和支持函数,用户没有必要知道数据结构的实现细节,减少这些实现细节就可以降低应用程序的复杂度。此外,这样也不会引诱用户使用数据结构的内部细节,如果用户使用了,之后数据结构的实现发生变化后会导致问题。

    说的直白一点就是,你不能通过该指针访问任何元素。

    创建和使用不透明指针

    不透明指针用来在 C 中实现数据封装。一种方法是在头文件中声明不包含任何实现细节的结构体,然后在实现文件中定义与数据结构的特定实现配合使用的函数。数据结构的用户可以看到声明和函数原型,但是实现会被隐藏(在 .c/.obj 文件中)。只有使用数据结构所需的信息会对用户可见,如果太多的内部信息可见,用户可能会使用这些信息,从而产生依赖。一旦内部结构发生变化,用户的代码可能就会失效。我们创建一个简单的链表来演示不透明指针的用法。

    link.h

    #ifndef TEST_C_LINK_H
    #define TEST_C_LINK_H
    
    typedef void *Data;
    typedef struct _linkedList LinkedList;
    
    LinkedList* getLinkedListInstance();
    void removeLinkedListInstance();
    void addNode(LinkedList*, Data);
    Data removeNode(LinkedList*);
    
    #endif // TEST_C_LINK_H
    

    Data 声明为 void 指针,这样允许实现处理任何类型的数据。LinkedList 的类型定义用了名为 _linkedList 的结构体,这个结构体的定义在实现文件中,对用户隐藏。我们提供来四种方法来使用链表。getLinkedListInstance() 函数获取 LinkedList 实例,一旦不再需要链表就应该调用 removeLinkedListInstance() 函数来释放内存。通过传递链表指针可以让函数处理一个或多个链表。

    要将数据添加到链表,需要用 addNode() 函数,我们给它传递链表和要添加到链表的数据指针。removeNode() 函数会返回链表头部的数据。我们把链表的实现在名为 link.c 的独立文件中。

    link.c

    #include <stdlib.h>
    #include "link.h"
    
    typedef struct _node
    {
        Data *data;
        struct _node *next;
    } Node;
    
    struct _linkedList
    {
        Node *head;
    };
    
    LinkedList *getLinkedListInstance()
    {
        LinkedList *list = (LinkedList *) malloc(sizeof(LinkedList));
        list->head = NULL;
        return list;
    }
    
    void removeLinkedListInstance(LinkedList *list)
    {
        Node *tmp = list->head;
        while (tmp != NULL)
        {
            free(tmp->data);
            Node *current = tmp;
            tmp = tmp->next;
            free(current);
        }
        free(list);
    }
    
    void addNode(LinkedList *list, Data data)
    {
        Node *node = (Node *) malloc(sizeof(Node));
        node->data = data;
        if (list->head == NULL)
        {
            list->head = node;
            node->next = NULL;
        } else
        {
            node->next = list->head;
            list->head = node;
        }
    }
    
    Data removeNode(LinkedList *list)
    {
        if (list->head == NULL)
        {
            return NULL;
        } else
        {
            Node *tmp = list->head;
            Data *data;
            list->head = list->head->next;
            data = tmp->data;
            free(tmp);
            return data;
        }
    }
    
    

    一个简单的链表就实现好了,那么我们怎么使用呢?

    test.c

    #include <stdio.h>
    #include <stdlib.h>
    
    
    #include "link.h"
    
    typedef struct {
        char *username;
        int age;
    }Person;
    
    void displayPerson(Person*);
    
    int main(){
        LinkedList *list = getLinkedListInstance();
    
        Person *person = (Person *)malloc(sizeof(Person));
        person->username = "jack";
        person->age = 12;
    
        Person *person2 = (Person *)malloc(sizeof(Person));
        person2->username = "jobs";
        person2->age = 15;
    
        addNode(list, person);
        addNode(list, person2);
    
        person = removeNode(list);
        displayPerson(person);
    
        person = removeNode(list);
        displayPerson(person);
    
        removeLinkedListInstance(list);
    
        return 0;
    }
    
    void displayPerson(Person *person){
        printf("username is : %s, age is : %d\n", person->username, person->age);
    }
    
    

    LinkedList 就是一个不透明指针,LinkedList 中的成员对使用者隐藏,只提供必要的方法给使用者,隐藏了实现细节。这个就类似于面向对象中的封装。


    参考

    相关文章

      网友评论

        本文标题:C 迷你系列(五)不透明指针

        本文链接:https://www.haomeiwen.com/subject/ycccxltx.html