当前位置: 首页 > 编程日记 > 正文

C面向对象之透明指针的运用

不透明指针(opaque pointer)可以用来在C中实现封装。

什么是不透明指针(opaque pointer)

从字面意思来看,“不透明”意味着看不到内部,因此“不透明指针”即看不到内部定义的指针。这样说有些抽象,我们来看个例子:

#include <stdio.h>
typedef void   *opque_data;
typedef struct AAA *opque_stru;int main()
{opque_data data = 0;opque_stru stru = 0;printf("Hello, World! \n");return 0;
}

上面的程序可以build通过(也许你会觉得疑惑),data和stru 指针所指的type(AAA)细节是什么,我们不得而知。我们可以自由的操纵这种指针,但无法解引用,即无法查看指针所指向结构的内部信息,只有接口的实现才有这种特权。

透明指针面向对象应用

void *型指针作为一种通用的指针,可以和其它任何类型的指针(函数指针除外)相互转化而不需要类型强制转换,但不能对它进行解引用及下标操作。

在.h文件中声明不包含任何实现细节的结构体,在.c中定义与数据结构的特定实现函数。用一个链表的代码(来自《深入理解C指针》)来说明透明指针的用法。

下面链表的代码中,link并没有与具体的data绑定,而是关联一个void *Data.

link.h

#ifndef LINK_H
#define LINK_Htypedef void* Data;  /* opaque pointer */typedef struct _linkedList LinkedList;
LinkedList* getLinkedListInstance();
void removeLinkedListInstance(LinkedList* list);
void addNode(LinkedList*, Data);
Data removeNode(LinkedList *);#endif

link.c

#include "link.h"
#include <stdlib.h>typedef struct _node{Data* data;   /*here use “Data data;” is also ok */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); /* potential memeory leak, it denpeds on if any pointer inside real type of 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 = tmp->data;list->head = list->head->next;free(tmp);   /* only free node, data is not free here */return data;  /* notes: data inside node returned, client need to free it,  */}
}

下面我们定义一个具体的node 数据类型Person.

person.h

#ifndef PERSON_H
#define PERSON_Htypedef struct _person{char* firstName;char* lastName;char* title;unsigned int age;
} Person;void initPerson(Person *personPtr, const char* firstNamePtr, const char* lastNamePtr, const char* titlePtr, unsigned int age);
void delePerson(Person *personPtr);
void dispPerson(Person *personPtr);#endif

person.c

#include "person.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void initPerson(Person *personPtr, const char* firstNamePtr, const char* lastNamePtr, const char* titlePtr, unsigned int age)
{personPtr->firstName = (char *)malloc(strlen(firstNamePtr) + 1);strcpy(personPtr->firstName, firstNamePtr);personPtr->lastName = (char *)malloc(strlen(lastNamePtr) + 1);strcpy(personPtr->lastName, lastNamePtr);personPtr->title = (char *)malloc(strlen(titlePtr) + 1);strcpy(personPtr->title, titlePtr);personPtr->age = age;
}void delePerson(Person *personPtr)
{free(personPtr->firstName);free(personPtr->lastName);free(personPtr->title);
}void dispPerson(Person *personPtr)
{printf("%s info name: %s %s\t title: %s\tage: %d\n", personPtr->firstName, personPtr->firstName, personPtr->lastName, personPtr->title, personPtr->age);
}

main.c

#include "link.h"
#include "person.h"
#include <stdio.h>int main(int argc, char **argv)
{LinkedList *list = getLinkedListInstance();Person *person = (Person *)malloc(sizeof(Person));initPerson(person, "Ricky", "ZEK", "Acmen", 36);addNode(list, person);person = (Person *)malloc(sizeof(Person));initPerson(person, "John", "OPP", "Develop", 28);addNode(list, person);person = (Person *)malloc(sizeof(Person));initPerson(person, "Ami", "VIV", "pet", 2);addNode(list, person);person = removeNode(list);dispPerson(person);delePerson(person);free(person);person = removeNode(list);dispPerson(person);delePerson(person);free(person);removeLinkedListInstance(list); /*memory leak, you can think of it */return 0;
}

相关文章:

支付宝 php rsa算法,:PHP支付宝接口RSA验证

这两天一直困扰的PHP RSA签名验证问题终于解决了&#xff0c;由于之前RSA接触的不多&#xff0c;再加上官方至今还未有PHP的SDK可供参考&#xff0c;因此走了一些弯路&#xff0c;写在这里和大家分享。虽然支付宝官方还未提供相关SDK&#xff0c;PHP确实可以实现RSA方式的签名&…

int与string转换

参考&#xff1a; http://greatverve.cnblogs.com/archive/2012/10/24/cpp-int-string.html 转载于:https://www.cnblogs.com/predator-wang/p/4789775.html

更改Jenkins升级站点

更新地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 【图示】&#xff1a;

Android 模仿微信启动动画(转)

本文内容 环境项目结构演示微信启动动画本文演示微信启动动画。请点击此处下载&#xff0c;自行调试。 顺便抱怨一下&#xff0c;实践性&#xff08;与研究性质的相对&#xff09;技术博的“七宗罪”&#xff1a; 第一宗罪&#xff0c;错字连篇&#xff0c;逻辑不清&#xff1b…

navicat for mysql收藏夹

navicat for mysql如果库表非常多的化&#xff0c;每次输入表名比较繁琐。 可以进入收藏夹便于快速打开经常使用的库表。 打开要入收藏夹的表&#xff0c;文件-添加收藏夹。 也可以快捷键shiftctrl1 如果已经有3个占用了&#xff0c;则自动跳到第4个栏位 也可以快捷键shiftctrl…

C 变量的作用域

下面的程序输出什么&#xff1f;思考一下 #include <stdio.h>// Driver Code int main() {{int x 10, y 20;{// The outer block contains// declaration of x and// y, so following statement// is valid and prints// 10 and 20printf("x %d, y %d\n",…

oracle字段重复新增错误,oracle在已有重复数据的列上创建唯一约束

在有重复数据的列上添加unique constraints,大家正常的解决办法就修改重复数据,但也可以 保留重复数据,使约束对以后的数据有限制,不过我们还可以用以下的方法来添加唯一约束. SQL create table aa(num number(6),email varchar2(32)); 表已创建。 SQL insert在有重复数据的列上…

poj_3067 树状数组

题目大意 左右两个竖排&#xff0c;左边竖排有N个点&#xff0c;从上到下依次标记为1,2,...N; 右边竖排有M个点&#xff0c;从上到下依次标记为1,2....M。现在从K条直线分别连接左边一个点和右边一个点&#xff0c;求这K条直线的交点个数&#xff08;左右竖排上的点不算做交点&…

2022-2028年中国自主可控行业深度调研及投资前景预测报告(全卷)

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国自主可控行业市场行业相关概述、中国自主可控行业市场行业运行环境、分析了中国自主可控行…

linux /etc/fstab文件参数求解释

2019独角兽企业重金招聘Python工程师标准>>> # cat /etc/fstab# # /etc/fstab # Created by anaconda on Mon Dec 17 09:06:53 2012 # # Accessible filesystems, by reference, are maintained under /dev/disk # See man pages fstab(5), findfs(8), mount(8) and…

C运算符优先级笔记

1. 指针数组 int *p[5]; [] 大于 * 2. 强制类型() 与 成员选择(./->) #include <stdlib.h>typedef struct {int data;int time; } data_t;int main() {data_t *p (data_t *)malloc(sizeof(data_t));int t (data_t *)p->time; /*focus: -> 大于 (data_t)*/f…

移动应用开发—— 如何搭建开发大型的应用架构?

什么是一个好的应用架构&#xff1f;怎么才能搭建大型的应用架构&#xff1f;其实每个人在工作几年之后都会有这个疑问&#xff0c;都在寻求好点的框架&#xff0c;那么小编我总结一下我的经验给大家。 其实对于客户端&#xff0c;一个好的应用架构&#xff0c;复杂度不亚于服务…

4104 oracle 数据文件名,Oracle 11g 常遇到ora-01034错误,这是为什么?

Errors in file d:\app\gerry\diag\rdbms\orcl\orcl\trace\orcl_psp0_5252.trc:ORA-27300: OS system dependent operation:CreateThread failed with status: 8ORA-27301: OS failure message: 存储空间不足&#xff0c;无法处理此命令。ORA-27302: failure occurred at: ssth…

Linux(CentOS6.5)中安装maven

Linux(CentOS6.5)中安装maven 1.上传相关包(*.tar.gz等) 使用相关软件上传或用Xshell连接后下载命令&#xff1a;yum install lrzsz 2.安装maven 1> 官网下载apache-maven-3.6.0-bin.tar.gz压缩包&#xff0c;上传到CentOS上&#xff08;目录自选&#xff09;。官网地址…

Spring+Hibernate项目在weblogic中部署的一些问题

2019独角兽企业重金招聘Python工程师标准>>> Hibernate JPA Jar包冲突&#xff0c;解决方法有两种&#xff0c; 第一种&#xff1a;将hibernate-jpa-2.0-api-1.0.1.Final.jar复制到当前weblogic域所使用的jdk目录下的\jdk160_29\jre\lib\ext目录下。 第二种&#xf…

Oracle語句大全

1. Oracle安装完成后的初始口令? internal/oracle sys/change_on_install system/manager scott/tiger sysman/oem_temp 2. ORACLE9IAS WEB CACHE的初始默认用户和密码&#xff1f; administrator/administrator 3. oracle 8.0.5怎么创建数据库? …

怎么编写段错误(Segmentation fault)的程序

On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception. 1.最常见的SEGV: 访问0地址 #include <stdio.h…

aix oracle11g 静默安装包,10g for AIX 静默安装

1 操作系统检查版本&#xff1a;oslevel -s位数&#xff1a;lslpp -L | /usr/bin/grep bos.64bit (软件位数)getconf KERNEL_BITMODE (硬件位数)2 用户检查用户&#xff1a; id oracleUMASK设置&#xff1a; 022环境变量&#xff1a;LD_LIBRARY_PATH &#xff0c;LIBPATH&…

Html_div圆角

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head><title>CSS3实现DIV圆角 - CSS3教…

2022-2028年中国自热米饭市场竞争策略及行业投资潜力预测报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国自热米饭行业市场行业相关概述、中国自热米饭行业市场行业运行环境、分析了中国自热米饭行…

使用getopt处理shell脚本的参数

getopt命令并不是bash的内建命令&#xff0c;它是由util-linux包提供的外部命令。相比较bash 的内置命令&#xff0c;getopt不只支持短参-s&#xff0c;还支持--longopt的长参数&#xff0c;甚至支持-longopt的简化参数。getopt可以用于tcsh其它的shell。现在就以系统自带的帮助…

Java基础教程——包装类

Java出道之时&#xff0c;自诩为“纯面向对象的语言”&#xff0c;意思是之前的所谓“面向对象语言”不纯。 但是&#xff0c;有人指责Java也不纯——8种基本类型并非类类型。为此&#xff0c;Java为他们提供可对应的类类型&#xff0c;是为“包装类”。 包装类 Java的八种基本…

linux kernel list_head

​​​​​​​Play with kernel list_head, three exampleshttps://www.fatalerrors.org/a/play-with-kernel-list_head-three-examples-of-super-cattle.html一篇介绍linux 内核链表的非常精彩的文章。

oracle rman实时备份吗,ORACLE-RMAN自动备份和恢复

以下介绍的是每周1-6增量备份&#xff0c;每周日全量备份。通过系统启动自动化任务[oracleorcl ~]$ crontab -l10 00 * * 0 /home/scripts/rmanlevel0.sh10 00 * * 1,2,3,4,5,6 /home/scripts/rmanlevel1.sh30 00 * * * /home/oracle/report/awr.sh[oracleorcl ~]$ cat /home…

hdu 5438 Ponds 拓扑排序

Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid1001&cid621Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, and there will not be more than o…

CentOS6安装nodejs

Nodejs是JavaScript的一种运行环境&#xff0c;是一个服务端的JavaScript解释器。 NPM是Nodejs的包管理器。 Nodejs包含npm&#xff0c;所以安装完nodejs后npm默认也被安装。 安装步骤&#xff1a; # /usr/local/srcwget http://nodejs.org/dist/v6.7.0/node-v6.7.0-linux-…

Codeforces Round #FF 446 C. DZY Loves Fibonacci Numbers

參考&#xff1a;http://www.cnblogs.com/chanme/p/3843859.html 然后我看到在别人的AC的方法里还有这么一种神方法&#xff0c;他预先设定了一个阈值K,当当前的更新操作数j<K的时候&#xff0c;它就用一个类似于树状数组段更的方法&#xff0c;用一个 d数组去存内容&#x…

Java 基本概念

Java 基本概念 1. Java 语言的优点? 简单、高效 Java 语言与 C 类似&#xff0c;如果用户了解 C 和面向对象的概念&#xff0c;就可以很快编写出 Java 程序&#xff1b;此外&#xff0c;Java 又不同于诸如 C 语言提供的各种各样的方法&#xff0c;它只提供了基本的方法&#x…

list_for_each_safe

list_for_each_safeBidirect-list list_for_each_safe().https://biscuitos.github.io/blog/LIST_list_for_each_safe/

oracle恢复是怎么看进度,Oracle中查看慢查询进度的脚本分享

Oracle一个大事务的sql往往不知道运行到了哪里,可以使用如下sql查看执行进度。代码如下:404_6set linesize 400;H_404_6set pagesize 400;H_404_6col sql_text format a100;H_404_6col opname format a15;H_404_6SELECT se.sid,H_404_6opname,H_404_6TRUNC (sofar / totalwork …