不透明指针 
C 不支持面向对象编程,不过,借助不透明指针,我们也可以使用 C 封装数据以及支持某种程度的多态行为。我们可以隐藏数据结构的实现和支持函数,用户没有必要知道数据结构的实现细节,减少这些实现细节就可以降低应用程序的复杂度。此外,这样也不会引诱用户使用数据结构的内部细节,如果用户使用了,之后数据结构的实现发生变化后会导致问题。
 
说的直白一点就是,你不能通过该指针访问任何元素。
创建和使用不透明指针 不透明指针用来在 C 中实现数据封装。一种方法是在头文件中声明不包含任何实现细节的结构体,然后在实现文件中定义与数据结构的特定实现配合使用的函数。数据结构的用户可以看到声明和函数原型,但是实现会被隐藏(在 .c/.obj 文件中)。只有使用数据结构所需的信息会对用户可见,如果太多的内部信息可见,用户可能会使用这些信息,从而产生依赖。一旦内部结构发生变化,用户的代码可能就会失效。我们创建一个简单的链表来演示不透明指针的用法。
link.h
1 2 3 4 5 6 7 8 9 10 11 12 #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   
 
Data 声明为 void 指针,这样允许实现处理任何类型的数据。LinkedList 的类型定义用了名为 _linkedList 的结构体,这个结构体的定义在实现文件中,对用户隐藏。我们提供来四种方法来使用链表。getLinkedListInstance() 函数获取 LinkedList 实例,一旦不再需要链表就应该调用 removeLinkedListInstance() 函数来释放内存。通过传递链表指针可以让函数处理一个或多个链表。
要将数据添加到链表,需要用 addNode() 函数,我们给它传递链表和要添加到链表的数据指针。removeNode() 函数会返回链表头部的数据。我们把链表的实现在名为 link.c 的独立文件中。
link.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 #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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #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 中的成员对使用者隐藏,只提供必要的方法给使用者,隐藏了实现细节。这个就类似于面向对象中的封装。
 
参考