C语言中的不透明指针和对象
在C语言中,如果我们想实现类似于面向对象的方法,把接口API
暴露给使用者,而内部数据隐藏起来私有。该怎么办呐?本文介绍一种实用的设计模式,使用不透明指针(句柄)实现类似于面向对象的操作。
不透明指针是一种很好的设计模式。
在C语言中构造一个对象:
- 定义一个结构包含我们需要的数据
- 定义一些方法(函数)来处理一些事情,这些函数的第一个参数是结构的指针
- 申明一个变量作为对象的实例
这种不透明数据结构的实现方式多在底层操作系统中用到,最近看freeRTOS
代码,其中的核心数据结构任务控制块就是在task.c
文件中实现,在task.h
中则是使用这样一个不透明结构体TaskHandle_t
,其内部结构struct tskTaskControlBlock
在task.c
中实现。
//task.h中不透明结构体(句柄)定义如下
struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
typedef struct tskTaskControlBlock * TaskHandle_t;
//task.s中定义结构体的具体内容
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
#endif
...
#if ( configUSE_POSIX_ERRNO == 1 )
int iTaskErrno;
#endif
} tskTCB;
下面举一个例子,介绍不透明指针的用法。例子中定义一个结构体,里面包含两个数据成员,要构建这样一个对象,对外提供一个算法。例子中这个算法很简单,就是两个数据加起来,返回计算结果。
例子中三个文件:
main.c
test.c
test.h
test.c
文件
#include "test.h"
#include "stdlib.h"
typedef struct myDataType
{
int a;
int b;
}ST_MyData_T;
myDataHandle CreatMyData(int a, int b)
{
myDataHandle pstmyData = malloc(sizeof(myDataHandle));
pstmyData->a = a;
pstmyData->b = b;
return pstmyData;
}
int GetMyResult(myDataHandle pstVal)
{
return (pstVal->a)*(pstVal->b);
}
test.h
文件
#ifndef _TEST_H_
#define _TEST_H_
struct myDataType;
typedef struct myDataType* myDataHandle;
extern myDataHandle CreatMyData(int a, int b);
extern int GetMyResult(myDataHandle pstVal);
#endif //_TEST_H_
main.c
文件
#include <stdio.h>
#include "test.h"
void main(){
myDataHandle pmydata;
pmydata = CreatMyData(2,3);
printf("result = %d\n",GetMyResult(pmydata));
}
在main.c
中使用不透明结构体类型定义一个对象(句柄),使用接口函数接口来操作对象,因为对象的类型没有直接在.h
文件中定义,无法直接访问指针中的成员,起到了隐藏对象成员的作用。
参考:
Practical Design Patterns: Opaque Pointers and Objects in C: https://interrupt.memfault.com/blog/opaque-pointers