Я рассматриваю возможность реализации простого интерфейса на языке C.Непрозрачные структуры с несколькими определениями
Ключевой особенностью является то, что он предоставит несколько определений для непрозрачной структуры, предоставленной публичным заголовком интерфейса, то есть различные реализации предоставят разные данные подкладывания для этой структуры (так что в разных единицах перевода одна и та же структура будет иметь различная реализация).
Я не мог найти никакой ссылки, будет ли это хорошим или плохим шаблоном проектирования. По крайней мере, это, по-видимому, не нарушает строгое правило псевдонимов, полагаясь только на последовательный порядок и дополнение для общего первого элемента (ов), что гарантируется стандартом C (насколько я вижу). Конечно, я знаю о шаблонах, ориентированных на op в 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;
}
Возможно, интерфейс должен предоставить другой файл заголовка для исполнителей, обеспечивая определение заголовка структуры, содержащего указатели на функции. Возможно, он мог бы даже указать на структуру классов, содержащую те, которые минимизируют размеры объектов для классов со многими методами.
Спасибо!Для компилятора, который я аргументировал тем, что между различными единицами компиляции, у компилятора нет памяти (того, как она преобразует структуру), поэтому чтобы все работало, оно должно соответствовать макете и дополнению. Также это актуально: http://stackoverflow.com/questions/2748995/c-struct-memory-layout, что стандарт C обеспечивает поддержание порядка. Они вместе означали бы, что идентичные головы структуры должны скомпилироваться для идентичной компоновки. Конечно, оптимизация времени соединения, как вы упомянули, все еще может появиться в игре. – Jubatian
@Jubatian: Я считаю неправдоподобным, что авторы C89 столкнулись с проблемой детализации различных аспектов макета, если бы они не предполагали, что указатели на вещи с одинаковыми макетами должны использоваться взаимозаменяемо, но авторы компилятора вместо этого полагают, что авторы Стандарта делали такие вещи без всякой причины. – supercat
Если компилятор не ведет себя в соответствии со стандартом, когда и где он указан, это ошибка компилятора. Где же этот трекер ошибок? (однако могут быть задокументированы исключения) – Jubatian