C编程使用结构正向声明将接口与实现分离

C编程使用结构正向声明将接口与实现分离,c,C,我正在编写一个C程序,并使用GCC4.4.6进行编译。我不想使用C++编译器。 我正在实现一个组件,我打算在运行时让该组件的几个实例处于活动状态,并由其他组件拥有 作为一种将接口的定义与其实现分离并隐藏其在该实现中使用的内部结构和数据类型的方法,我希望使用前向结构声明 接口文件:组件.h struct _hidden_implementation_type; typedef struct _hidden_implementation_type visible_type_to_clients;

我正在编写一个C程序,并使用GCC4.4.6进行编译。我不想使用C++编译器。 我正在实现一个组件,我打算在运行时让该组件的几个实例处于活动状态,并由其他组件拥有

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

接口文件:组件.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;
};
int main(int argc, char** argv)
{
    visible_type_to_clients a;
    return component_function1(a);
}  
客户端文件:main.c

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

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

您就快到了。您的接口必须是指向不透明类型的指针:

struct hidden_implementation_type;
typedef struct hidden_implementation_type visible_type_to_clients;

int component_function1(visible_type_to_clients *instance_type);
以及:

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

visible_type_to_clients *new_visible(void);
要创建该类型的值并返回指针,然后可以使用:

int main(void)
{
    visible_type_to_clients *a = new_visible();
    return component_function1(a);
}
基本上,客户端将无法在类型的堆栈(或全局结构)上创建结构,因为您没有告诉编译器类型有多大。但是您可以处理指针,类型化指针比“非类型化”指针要安全得多

为了简单起见,我省略了错误检查。我重拨了结构标记名,但没有前导下划线,因为出于所有实际目的,以下划线开头的名称都是无效的。我同意:

typedef struct VisibleType VisibleType;

标记和类型名称相同。

隐藏结构有其优点和缺点。如果没有构造函数,客户端永远无法分配隐藏结构。隐藏结构需要析构函数,客户端需要记住调用它。这是优势还是劣势取决于您的需求

下面是两个比较的实现:

#include <stdio.h>
#include <stdlib.h>

/*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();
}
#包括
#包括
/*活泼的*/
类型定义结构
{
整数;
}可见的;
void VISIBLE_INIT(VISIBLE*me,int num);
无效可见打印(常量可见*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);}
/*秘密*/
结构客户端;
无效客户端(结构客户端**me,int num);
无效客户端数据(结构客户端**me);
无效客户端打印(const-struct-CLIENT*me);
/*秘密*/
类型定义结构客户端
{
整数;
}客户;
无效客户端(客户端**me,int num)
{
如果(我)
{
*me=(客户*)malloc(客户规模);
(*me)->number=num;
}
}
无效客户端数据(客户端**me)
{
如果(我和我)自由(*我);
*me=0;
}
void CLIENT_PRINT(const CLIENT*me){if(me)printf(“%i\n”,me->number);}
/*main.c*/
无效可见()
{
VISIBLE vis;//客户端可以分配内存
可见光初始(&vis,4);
可见光打印(&vis);
//如果不需要析构函数,客户端就不需要调用析构函数
}
void hidden()
{
客户机*隐藏;
客户端(隐藏和隐藏,3);
客户端打印(隐藏);
CLIENT_DTOR(&hidden);//永远不允许客户端忘记析构函数
}
int main()
{
可见();
隐藏();
}

通常的方法包括指向结构类型的指针,其中结构的内部细节对客户端不可见。
instance\u type
是实例本身,而不是类型。我认为typedef在这里不提供任何内容。