4

我正在开发一个大型项目,该项目作为静态 c 库和一个头文件提供给我们的客户,其中包含我们公开的 API 的原型。该项目有两个相似但独特的构建,它们需要在标头中公开不同的数据结构。我正在尝试提出最佳设计,以允许单个 API 函数根据构建使用不同的数据结构。到目前为止,这是我的想法,但我担心这是一个糟糕的设计。

我的功能将像这样实现

void foo(void *generic_data_struct)
{
#ifdef BUILD1
   build1_t *data_struct = generic_data_struct;
#else
   build2_t *data_struct = generic_data_struct;
#endif
...
}

根据客户订单的构建,公开的 API 标头将是

void foo(build1_t *data_struct);

或者

void foo(build2_t *data_struct);

这是一个合理的设计模式还是不赞成?谢谢!

4

4 回答 4

5

struct foo;对于这种事情,使用不透明类型 ( ) 几乎总是比使用void指针更好。

每当您有变体构建时,都非常希望最大限度地减少#ifdefs 的数量。我建议您使用 eq- 的建议,但要使用 typedef 排除函数原型的变化:

/* header file */
#ifdef BUILD1
typedef build1_t generic_t;
#else
typedef build2_t generic_t;
#endif

void foo(generic_t *);
void bar(generic_t *);
/* etc */

每当实际行为基于 改变时,您仍然需要在 、 等内部使用 #ifdefs ,但您不需要在每个函数的声明和定义中使用它们。foobarBUILD1

于 2012-08-28T18:04:20.020 回答
3

为什么不这样:

#ifdef BUILD1
foo(build1_t *data_struct)
#else
foo(build2_t *data_struct)
#endif
{
  /* ... */
}

AFAIK,该标准不要求不同的指针类型按位兼容,因此您的原始想法可能无法移植到所有可能的实现。如果原型也被使用void*(但在这个过程中当然会牺牲一些类型安全),那将会是这样。

于 2012-08-28T18:01:01.903 回答
1
struct generic_struct {
    union {
        struct specific_struct_1 struct_1;
        struct specific_struct_2 struct_2;
    };
};

这为您提供了在重叠空间中保存两个结构定义的单一类型。

于 2012-08-28T18:04:09.997 回答
1

我建议您不要使用编译时指令来分离功能。在运行时选择;使用 if() 语句并有一些状态指示模式。

于 2012-08-28T18:08:03.573 回答