3

我正在考虑用 C 语言实现一个简单的接口模式。

一个关键特征是它将为接口的公共标头提供的不透明结构提供多个定义,也就是说,不同的实现将为该结构提供不同的底层数据(因此跨不同的翻译单元,相同的结构将具有不同的实现)。

无论这将是一个好还是坏的设计模式,我都找不到任何参考。至少它似乎没有违反严格的别名规则,只依赖于公共第一个元素的一致顺序和填充,这是由 C 标准保证的(据我所知)。当然,我知道 C 中面向对象的模式,但我看不到这个特定的模式被使用。

这可以接受吗?甚至使用过这样的模式吗?(我找不到任何东西)

为了便于理解,以下是三个源文件的工作示例:

reader.h(公共接口定义)

#ifndef READER_H
#define READER_H

typedef struct reader_s reader_t;

char reader_read(reader_t* r);

#endif

reader.c(接口的粘合逻辑)

#include "reader.h"

typedef char (reader_f)(reader_t*);

struct reader_s{
 reader_f* rfunc;
};

char reader_read(reader_t* r)
{
 return r->rfunc(r);
}

reader1.h(接口的实现,头文件)

#ifndef READER1_H
#define READER1_H

#include "reader.h"

reader_t* reader1_get(void);

#endif

reader1.c(接口的实现,代码)

#include "reader1.h"

typedef char (reader_f)(reader_t*);

struct reader_s{
 reader_f* rfunc;
 int       pos;
};

static char reader1_read(reader_t* r);

reader_t reader1_obj = {&reader1_read, 0};

reader_t* reader1_get(void)
{
 return &reader1_obj;
}

static char reader1_read(reader_t* r)
{
 char rval = 'A' + (r->pos);
 (r->pos) = (r->pos) + 1;
 if ((r->pos) == 24){ (r->pos) = 0; }
 return rval;
}

main.c(示例用法)

#include "reader1.h"
#include <stdio.h>

int main(void)
{
 reader_t* rd = reader1_get();
 int       i;

 printf("\n");
 for (i = 0; i < 60; i++){
  printf("%c", reader_read(rd));
 }
 printf("\n");

 return 0;
}

接口可能应该为实现者提供另一个头文件,提供包含函数指针的结构头的定义。也许它甚至可以指向一个包含那些以最小化具有许多方法的类的对象大小的类结构。

4

1 回答 1

1

C 标准中的任何内容都不会定义这种情况下的行为,但如果实现指定数据类型的存储格式以及处理模块间调用的方式,则可以定义行为作为结果。但是请注意,某些具有“链接时间优化”的实现可能并不总是以“正常”记录的方式执行模块间调用。

我唯一能看到这种方法可行的情况是,如果与类型关联的公共 API 希望允许代码直接声明该类型的实例或对它们使用赋值运算符,但又不想承诺为任何其他目的公开字段布局。在这种情况下,有一个包含类似uint32[]或的​​公共结构类型uint64[]即使处理该类型内部的所有代码都使用“真实”结构类型,这可能是一种合理的方法。如果内部结构类型发生变化,如果大小保持不变,这样的设计将避免重新编译客户端代码的需要。另一方面,对于可能需要启用 gcc 风格的基于类型的别名“优化”来处理的代码,我不会考虑任何此类设计,因为 gcc 故意对此类优化会破坏代码的地方视而不见。

于 2017-04-12T22:26:08.150 回答