plinth..
11
让我们来谈谈在过去被认为是最佳实践的完整工程解决方案.
结构的问题是一切都是公共的,所以没有数据隐藏.
我们可以解决这个问题
您创建两个头文件.一个是代码客户端使用的"公共"头文件.它包含这样的定义:
typedef struct t_ProcessStruct *t_ProcessHandle;
extern t_ProcessHandle NewProcess();
extern void DisposeProcess(t_ProcessHandle handle);
typedef struct t_PermissionsStruct *t_PermissionsHandle;
extern t_PermissionsHandle NewPermissions();
extern void DisposePermissions(t_PermissionsHandle handle);
extern void SetProcessPermissions(t_ProcessHandle proc, t_PermissionsHandle perm);
然后你创建一个私有头文件,其中包含如下定义:
typedef void (*fDisposeFunction)(void *memoryBlock);
typedef struct {
fDisposeFunction _dispose;
} t_DisposableStruct;
typedef struct {
t_DisposableStruct_disposer; /* must be first */
PID _pid;
/* etc */
} t_ProcessStruct;
typedef struct {
t_DisposableStruct_disposer; /* must be first */
PERM_FLAGS _flags;
/* etc */
} t_PermissionsStruct;
然后在您的实现中,您可以执行以下操作:
static void DisposeMallocBlock(void *process) { if (process) free(process); }
static void *NewMallocedDisposer(size_t size)
{
assert(size > sizeof(t_DisposableStruct);
t_DisposableStruct *disp = (t_DisposableStruct *)malloc(size);
if (disp) {
disp->_dispose = DisposeMallocBlock;
}
return disp;
}
static void DisposeUsingDisposer(t_DisposableStruct *ds)
{
assert(ds);
ds->_dispose(ds);
}
t_ProcessHandle NewProcess()
{
t_ProcessHandle proc = (t_ProcessHandle)NewMallocedDisposer(sizeof(t_ProcessStruct));
if (proc) {
proc->PID = NextPID(); /* etc */
}
return proc;
}
void DisposeProcess(t_ProcessHandle proc)
{
DisposeUsingDisposer(&(proc->_disposer));
}
会发生什么是您在公共头文件中为结构做出前向声明.现在你的结构是不透明的,这意味着客户不能与它们混在一起.然后,在完整声明中,在每个结构的开头都包含一个析构函数,您可以调用它.您可以为每个人使用相同的malloc分配器具有相同的dispose功能.您为要公开的元素创建公共set/get函数.
突然间,你的代码更加清晰.您只能从分配器或调用分配器的函数获取结构,这意味着您可以瓶颈初始化.您构建析构函数以便可以销毁对象.你去吧.顺便说一下,比t_DisposableStruct更好的名字可能是t_vTableStruct,因为它就是这样.您现在可以通过使用vTableStruct来构建虚拟继承,该vTableStruct是所有函数指针.你也可以用纯粹的oo语言(通常)做一些你不能做的事情,比如在运行中更改vtable的select元素.
最重要的一点是,有是用于制造结构安全和initializable工程模式.