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

不透明指針

C 不支持面向?qū)ο缶幊套吒椋贿^辛燥,借助不透明指針筛武,我們也可以使用 C 封裝數(shù)據(jù)以及支持某種程度的多態(tài)行為。我們可以隱藏?cái)?shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)和支持函數(shù)挎塌,用戶沒有必要知道數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)細(xì)節(jié)徘六,減少這些實(shí)現(xiàn)細(xì)節(jié)就可以降低應(yīng)用程序的復(fù)雜度。此外榴都,這樣也不會(huì)引誘用戶使用數(shù)據(jù)結(jié)構(gòu)的內(nèi)部細(xì)節(jié)待锈,如果用戶使用了,之后數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)發(fā)生變化后會(huì)導(dǎo)致問題嘴高。

說(shuō)的直白一點(diǎn)就是竿音,你不能通過該指針訪問任何元素。

創(chuàng)建和使用不透明指針

不透明指針用來(lái)在 C 中實(shí)現(xiàn)數(shù)據(jù)封裝拴驮。一種方法是在頭文件中聲明不包含任何實(shí)現(xiàn)細(xì)節(jié)的結(jié)構(gòu)體春瞬,然后在實(shí)現(xiàn)文件中定義與數(shù)據(jù)結(jié)構(gòu)的特定實(shí)現(xiàn)配合使用的函數(shù)。數(shù)據(jù)結(jié)構(gòu)的用戶可以看到聲明和函數(shù)原型套啤,但是實(shí)現(xiàn)會(huì)被隱藏(在 .c/.obj 文件中)宽气。只有使用數(shù)據(jù)結(jié)構(gòu)所需的信息會(huì)對(duì)用戶可見,如果太多的內(nèi)部信息可見,用戶可能會(huì)使用這些信息萄涯,從而產(chǎn)生依賴绪氛。一旦內(nèi)部結(jié)構(gòu)發(fā)生變化,用戶的代碼可能就會(huì)失效涝影。我們創(chuàng)建一個(gè)簡(jiǎn)單的鏈表來(lái)演示不透明指針的用法枣察。

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 指針,這樣允許實(shí)現(xiàn)處理任何類型的數(shù)據(jù)袄琳。LinkedList 的類型定義用了名為 _linkedList 的結(jié)構(gòu)體询件,這個(gè)結(jié)構(gòu)體的定義在實(shí)現(xiàn)文件中,對(duì)用戶隱藏唆樊。我們提供來(lái)四種方法來(lái)使用鏈表宛琅。getLinkedListInstance() 函數(shù)獲取 LinkedList 實(shí)例,一旦不再需要鏈表就應(yīng)該調(diào)用 removeLinkedListInstance() 函數(shù)來(lái)釋放內(nèi)存逗旁。通過傳遞鏈表指針可以讓函數(shù)處理一個(gè)或多個(gè)鏈表嘿辟。

要將數(shù)據(jù)添加到鏈表,需要用 addNode() 函數(shù)片效,我們給它傳遞鏈表和要添加到鏈表的數(shù)據(jù)指針红伦。removeNode() 函數(shù)會(huì)返回鏈表頭部的數(shù)據(jù)。我們把鏈表的實(shí)現(xiàn)在名為 link.c 的獨(dú)立文件中淀衣。

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;
    }
}

一個(gè)簡(jiǎn)單的鏈表就實(shí)現(xiàn)好了昙读,那么我們?cè)趺词褂媚兀?/p>

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 就是一個(gè)不透明指針,LinkedList 中的成員對(duì)使用者隱藏膨桥,只提供必要的方法給使用者蛮浑,隱藏了實(shí)現(xiàn)細(xì)節(jié)。這個(gè)就類似于面向?qū)ο笾械姆庋b只嚣。


參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載沮稚,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末册舞,一起剝皮案震驚了整個(gè)濱河市蕴掏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌调鲸,老刑警劉巖盛杰,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異线得,居然都是意外死亡饶唤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門贯钩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)募狂,“玉大人办素,你說(shuō)我怎么就攤上這事』銮睿” “怎么了性穿?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)雷滚。 經(jīng)常有香客問我需曾,道長(zhǎng),這世上最難降的妖魔是什么祈远? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任呆万,我火速辦了婚禮,結(jié)果婚禮上车份,老公的妹妹穿的比我還像新娘谋减。我一直安慰自己,他們只是感情好扫沼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布出爹。 她就那樣靜靜地躺著,像睡著了一般缎除。 火紅的嫁衣襯著肌膚如雪严就。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天器罐,我揣著相機(jī)與錄音梢为,去河邊找鬼。 笑死轰坊,一個(gè)胖子當(dāng)著我的面吹牛抖誉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播衰倦,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼旁理!你這毒婦竟也來(lái)了樊零?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤孽文,失蹤者是張志新(化名)和其女友劉穎驻襟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芋哭,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沉衣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了减牺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豌习。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡存谎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肥隆,到底是詐尸還是另有隱情既荚,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布栋艳,位于F島的核電站恰聘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吸占。R本人自食惡果不足惜晴叨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望矾屯。 院中可真熱鬧兼蕊,春花似錦、人聲如沸问拘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骤坐。三九已至绪杏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纽绍,已是汗流浹背蕾久。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拌夏,地道東北人僧著。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像障簿,于是被迫代替她去往敵國(guó)和親盹愚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容