不透明指針
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只嚣。