美文网首页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