C编程解耦接口实现与struct forward声明

我正在编写一个C程序并使用gcc 4.4.6进行编译。 我不想使用c ++编译器。

我正在实现一个组件,我打算在运行时实时拥有该组件的多个实例并由其他组件拥有。

作为将接口的定义与其实现分离并隐藏它在该实现中使用的内部结构和数据类型的手段,我希望使用前向结构声明。

接口文件: component.h

struct _hidden_implementation_type; typedef struct _hidden_implementation_type visible_type_to_clients; int component_function1(visible_type_to_clients instance); 

实现文件: component.c

 struct _hidden_implementation_type { int foo; }; 

客户端文件: main.c

 int main(int argc, char** argv) { visible_type_to_clients a; return component_function1(a); } 

我该如何工作? 还有什么其他方法可以允许多个组件实例化,并提供公共接口和实现之间的解耦?

你快到了。 您的界面必须是指向opaque类型的指针:

 struct hidden_implementation_type; typedef struct hidden_implementation_type visible_type_to_clients; int component_function1(visible_type_to_clients *instance_type); 

和:

 int main(void) { visible_type_to_clients *a = 0; return component_function1(a); } 

这至少会编译 – 但它不会做任何有用的事情。 您可能需要一个function,例如:

 visible_type_to_clients *new_visible(void); 

创建一个类型的值并返回一个指针,然后你可以使用:

 int main(void) { visible_type_to_clients *a = new_visible(); return component_function1(a); } 

基本上,客户端将无法在您的类型的堆栈(或全局结构)上创建结构,因为您没有告诉编译器类型有多大。 但是你可以处理指针 – 而且键入的指针比’untyped’void void *指针更安全。

为简单起见,我省略了错误检查。 我在没有前导下划线的情况下重新构造了结构标记名称,因为出于所有实际目的,以下划线开头的名称是为实现保留的 。 我跟着:

 typedef struct VisibleType VisibleType; 

标签和类型名称相同。

隐藏结构有利有弊。 没有构造函数的客户端永远不能分配隐藏的结构。 隐藏的结构需要析构函数,客户端需要记住调用它。 根据您的要求,这是一个优点或缺点。

以下是两个比较实现:

 #include  #include  /*VIVIBLE.h*/ typedef struct { int number; }VISIBLE; void VISIBLE_INIT(VISIBLE * me, int num); void VISIBLE_PRINT(const VISIBLE * me); /*VIVIBLE.c*/ void VISIBLE_INIT(VISIBLE * me, int num) { if(me) me->number = num; } void VISIBLE_PRINT(const VISIBLE * me) { if(me) printf("%i\n", me->number); } /*SECRET.h*/ struct CLIENT; void CLIENT_CTOR(struct CLIENT ** me, int num); void CLIENT_DTOR(struct CLIENT ** me); void CLIENT_PRINT(const struct CLIENT * me); /*SECRET.c*/ typedef struct CLIENT { int number; }CLIENT; void CLIENT_CTOR(CLIENT ** me, int num) { if (me) { *me = (CLIENT*)malloc(sizeof(CLIENT)); (*me)->number = num; } } void CLIENT_DTOR(CLIENT ** me) { if (me && *me) free(*me); *me = 0; } void CLIENT_PRINT(const CLIENT * me) { if(me) printf("%i\n", me->number); } /*main.c*/ void visible() { VISIBLE vis; // client can allocate memory VISIBLE_INIT(&vis, 4); VISIBLE_PRINT(&vis); //if there is no need for a destructor the client does not need to call one } void hidden() { CLIENT * hidden; CLIENT_CTOR(&hidden, 3); CLIENT_PRINT(hidden); CLIENT_DTOR(&hidden); //Client is never allowed to forget the destructor } int main() { visible(); hidden(); }