C中的opaque(抽象)数据类型
文件api.h
#include #ifndef API #define API struct trytag; typedef struct trytag try; void trial (try *); #endif
文件core.h
#ifndef CORE #define CORE struct trytag { int a; int b; }; #endif
文件func.c
#include "api.h" #include "core.h" void trial (try *tryvar) { tryvar->a = 1; tryvar->b = 2; }
文件main.c
#include "api.h" int main () { try s_tryvar; trial(&s_tryvar); printf("a = %d\nb = %d\n", s_tryvar.a, s_tryvar.b); }
当我编译时,我得到:
main.c:5: error: storage size of 's_tryvar' isn't known
如果我在main.c
包含core.h
,则不会出现此错误,因为在core.h
定义了core.h
。 但我希望结构try
隐藏到main.c
– 它不应该知道try
结构的成员。 我错过了什么?
我不认为你想做的事情是可能的。 编译器需要知道编译main.c
的try
结构有多大。 如果你真的希望它是不透明的,那么创建一个通用的指针类型,而不是直接在main()
中声明变量,而是使用alloc_try()
和free_try()
函数来处理创建和删除。
像这样的东西:
api.h:
#ifndef API #define API struct trytag; typedef struct trytag try; try *alloc_try(void); void free_try(try *); int try_a(try *); int try_b(try *); void trial (try *); #endif
core.h:
#ifndef CORE #define CORE struct trytag { int a; int b; }; #endif
func.c:
#include "api.h" #include "core.h" #include try *alloc_try(void) { return malloc(sizeof(struct trytag)); } void free_try(try *t) { free(t); } int try_a(try *t) { return t->a; } int try_b(try *t) { return t->b; } void trial(try *t) { t->a = 1; t->b = 2; }
main.c中:
#include #include "api.h" int main() { try *s_tryvar = alloc_try(); trial(s_tryvar); printf("a = %d\nb = %d\n", try_a(s_tryvar), try_b(s_tryvar)); free_try(s_tryvar); }
想想不透明的FILE结构如何在C中工作。你只使用指针,你需要一个像fopen()这样的函数来创建一个实例,并且需要一个像fclose()这样的函数来处理它。
问题出在main.c中,编译器还没有看到struct try
的定义。 因此,编译器仅限于使用指向struct try
指针。
您要做的是为您的API添加两个新function:
try *create_try(); void *destroy_try(try *t);
这些函数将分别调用malloc和free。
如果您不希望将结构限制为仅允许在堆上,则您将不得不放弃使其不透明。
有一种方法可以做一些技术上并不完全符合您要求的方法,但应该起到保持结构不透明同样的目的,同时支持非堆分配。
在api.h中,您声明了一个不透明的结构如下:
struct trytag_opaque { char data[sizeof(int)*2]; };
如果你想比它更不透明,你可以计算任何支持平台所需的最大结构大小,并使用:
struct trytag_opaque { char data[MAX_TRYTAG_SIZE]; };
然后你的api.h函数声明如下:
int try_a(struct trytag_opaque *t)
你的function代码如下:
int try_a(struct trytag_opaque *t_opaque) { trytag *t = (trytag *)t_opaque; ... }
你的main.c看起来像:
#include "api.h" int main() { struct trytag_opaque t; ... try_a(&t); ... }