我在头文件中定义了一个结构,如下所示:
typedef struct {
void *data;
} point;
Run Code Online (Sandbox Code Playgroud)
我希望让其他人不直接访问*数据,所以我想我会在.c文件中声明结构,并使用类似extern typedef struct point;头文件中的内容.然而,这不起作用.
实现这一目标的最佳方法是什么?
Gra*_*and 14
在您的(公共)头文件中:
typedef struct point point;
Run Code Online (Sandbox Code Playgroud)
在您的.c文件中:
struct point
{
void *data;
};
Run Code Online (Sandbox Code Playgroud)
请注意,代码的用户将无法再point在堆栈上创建,因为编译器不知道它有多大.您可能必须提供一个point_create()分配内存并将其地址返回给调用者的函数.
使用 C++
// Public.h
#include <stdlib.h>
typedef enum
{
None = 0,
PointType = 1
} Types;
typedef int Handle;
Handle CreateType(Types type);
int DeleteType(Handle object);
void IncrementX(Handle point);
void PrintPoint(Handle point);
Run Code Online (Sandbox Code Playgroud)
如您所见,您拥有创建和删除在枚举中定义的对象的通用方法。然后,使用该对象的方法将需要查找整数句柄以获取存储真实数据的元数据对象。如果您管理的对象很小,则这种设计效率不高,因为对于每个对象,都需要第二个对象来存储对象类型、句柄值和指向实际数据的指针。但是您可以获得更强大的安全保证,例如
您的 Api 的典型用法可能如下所示:
Handle h = CreateType(PointType);
IncrementX(h);
IncrementX(h);
PrintPoint(h);
DeleteType(h);
Run Code Online (Sandbox Code Playgroud)
在 private.cpp 中有一个超级秘密实现,其中存在 Handle 查找数组和一些辅助方法:
// Private.C
#include "stdafx.h"
#include <stdlib.h>
#include <Windows.h> // for ZeroMemory
#include "Public.h"
typedef struct
{
LPVOID pData;
Types type;
Handle handle;
} HandleInfo;
typedef struct
{
int x;
int y;
} Point;
HandleInfo *pAllocated;
int HandleBuffer = 0xffff;
unsigned char bInit = 0;
HandleInfo *GetFreeHandle()
{
int i;
if( !bInit )
{
pAllocated = (HandleInfo *) malloc(sizeof(HandleInfo)*HandleBuffer);
bInit = 1;
ZeroMemory(pAllocated, sizeof(HandleInfo)*HandleBuffer);
}
for(i=0; i<HandleBuffer; i++)
{
HandleInfo *pInfo = (pAllocated+i);
if( 0 == pInfo->handle )
{
pInfo->handle = i+1;
return pInfo;
}
}
return NULL;
}
HandleInfo * GetHandleInfo(Handle h)
{
if( h <= 0 || h >= HandleBuffer-1)
{
return NULL;
}
return (pAllocated+h-1);
}
Handle CreateType(Types typeId)
{
HandleInfo *pInfo;
pInfo = GetFreeHandle();
if( NULL == pInfo )
{
return -1;
}
pInfo->type = typeId;
switch(typeId)
{
case PointType:
pInfo->pData = malloc(sizeof(Point));
ZeroMemory(pInfo->pData, sizeof(Point));
break;
}
return pInfo->handle;
}
int DeleteType(Handle object)
{
HandleInfo *pInfo = GetHandleInfo(object);
if( NULL == pInfo )
{
return -1;
}
if( pInfo->handle != 0 )
{
free(pInfo->pData);
pInfo->pData = NULL;
pInfo->handle = 0;
return 1;
}
else
{
return 0; // Handle was already closed
}
}
void *GetObjectOfCorrectType(Handle object, Types type)
{
HandleInfo *p = GetHandleInfo(object);
if( p == NULL )
{
return NULL;
}
if( p->type != type)
{
return NULL; // handle has wrong object type
}
return p->pData;
}
void IncrementX(Handle point)
{
Point *pPoint = (Point *) GetObjectOfCorrectType(point, PointType);
if( pPoint == NULL )
{
return;
}
pPoint->x++;
}
void PrintPoint(Handle point)
{
Point *pPoint = (Point *) GetObjectOfCorrectType(point, PointType);
if( pPoint == NULL )
{
return;
}
printf("Point has x: %d y: %d", pPoint->x, pPoint->y);
}
Run Code Online (Sandbox Code Playgroud)
你的,阿洛伊斯·克劳斯