C中的opaque(抽象)数据类型

时间:2010-01-04 19:36:10

标签: c types abstract

文件api.h

#include <stdio.h>
#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

如果我在core.h中加入main.c,则此错误不会出现,因为core.h中定义了尝试。但我希望将结构try隐藏到main.c - 它不应该知道try结构的成员。我错过了什么?

4 个答案:

答案 0 :(得分:6)

我不认为你想做的事情是可能的。编译器需要知道编译try的{​​{1}}结构有多大。如果你真的希望它是不透明的,那么创建一个通用的指针类型,而不是直接在main.c中声明变量,使main()alloc_try()函数来处理创建和删除。 / p>

这样的事情:

api.h:

free_try()

core.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

func.c:

#ifndef CORE
#define CORE
struct trytag
{
    int a;
    int b;
};
#endif

main.c中:

#include "api.h"
#include "core.h"
#include <stdlib.h>

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;
}

答案 1 :(得分:1)

想想不透明的FILE结构如何在C中工作。你只使用指针,你需要像fopen()这样的函数来创建一个实例,并且需要像fclose()这样的函数来处理它。

答案 2 :(得分:1)

问题出在main.c中,编译器还没有看到struct try的定义。因此,编译器仅限于使用指向struct try的指针。

您要做的是在API中添加两个新功能:

try *create_try();
void *destroy_try(try *t);

这些函数将分别调用malloc和free。

如果您不希望将结构限制为仅允许在堆上,则您将不得不放弃使其不透明。

答案 3 :(得分:0)

有一种方法可以做一些技术上并不完全符合你要求的东西,但应该保持你的结构不透明同时支持非堆分配。

在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)

,您的功能代码如下:

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);
    ...
}