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

不透明指针

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 中的成员对使用者隐藏,只提供必要的方法给使用者,隐藏了实现细节。这个就类似于面向对象中的封装。


参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容