c语言透明指针,C语言创建和使用不透明指针

不透明指针用来在C中实现数据封装。一种方法是在头文件中声明不包含任何实现细节的结构体,然后在实现文件中定义与数据结构的特定实现配合使用的函数。数据结构的用户可以看到声明和函数原型,但是实现会被隐藏(在.c/.obj文件中)。

只有使用数据结构所需的信息会对用户可见,如果太多的内部信息可见,用户可能会使用这些信息,从而产生依赖。一旦内部结构发生变化,用户的代码可能就会失效。

我们会开发一个链表来说明不透明指针的用法。用户会用一个函数来获取链表指针,然后用这个指针来向链表添加信息以及从链表删除信息。链表的内部结构细节和支持函数对用户不可见。这个结构的唯一可见部分通过头文件提供,如下所示:

Data声明为void指针,这样允许实现处理任何类型的数据。LinkedList的类型定义用了名为_linkedList的结构体,这个结构体的定义在实现文件中,对用户隐藏。

我们提供了四种方法来使用链表。用户一开始用getLinkedListInstance函数来获取一个LinkedList实例,一旦不再需要链表就应该调用removeLinkedListInstance函数。通过传递链表指针可以让函数处理一个或多个链表。

要将数据添加到链表,需要用addNode函数,我们给它传递链表和要添加到链表的数据指针。removeNode方法会返回链表头部的数据。

链表的实现在名为link.c的独立文件中。实现的第一部分,如下所示,声明持有用户数据和下一个链表节点的结构体,接着是_linkedList结构体的定义。在这个简单的链表中,我们只用到了一个头指针:

实现文件的第二部分包含链表的四个支持函数的实现,第一个函数返回一个链表实例:

接着是removeLinkedListInstance函数的实现,如果有节点的话,它会释放链表中的所有节点,然后释放链表本身。如果节点引用的数据包含指针,这个实现可能会产生内存泄漏。一种解决方案是传递一个释放数据成员的函数:

addNode函数把第二个参数传入的数据添加到第一个参数指定的链表中。系统会为每个节点分配内存,然后将其和用户的数据关联起来。在这个实现中,总是将链表的节点添加到头部:

removeNode函数返回跟链表中第一个节点关联的数据。我们会调整头指针,让其指向链表中下个节点。接着返回数据,释放旧节点,将数据返回堆中。

注意 用户使用这种方法无需记住释放链表节点,从而避免了内存泄漏。这是隐藏实现细节的巨大优势:

为了说明这个数据结构的使用方法,我们会重用6.1节中开发的Person结构体及其函数。下面的代码会把两个人添加到链表中,然后删除。首先调用getLinkedListInstance函数来获取链表。接着,用initializePerson函数创建一个Person实例并用addNode函数将其添加到链表中。displayPerson函数会打印由removeNode函数返回的人。最后释放链表:

这种方法有几个有趣的地方。我们只能在link.c文件中创建_linkedList结构体的实例,这是因为如果没有完整的结构体声明就无法使用sizeof操作符。比如说,如果你试图在main函数中为这个结构体分配内存,如下所示,会得到一个语法错误:

产生的语法错误类似下面这样:

类型不完整是因为编译器看不到link.c文件中的实际定义。它只能看到_linkedList结构体的类型定义,而看不到结构体的实现细节。

我们不允许用户看到链表内部结构以及使用链表内部结构,并且会对用户隐藏结构体的任何变化。

只有四个支持函数的签名对用户是可见的,否则,用户就无法利用或修改实现细节。我们封装了链表结构及其支持函数,从而减轻了用户的负担。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值