C言語で簡単なインターフェースパターンを実現しようと考えています。
重要な特徴は、インターフェイスのパブリック ヘッダーによって提供される不透明な構造体に複数の定義を提供することです。つまり、実装が異なれば、その構造体に異なる基盤となるデータが提供されます (したがって、異なる翻訳単位間では、同じ構造体が異なる実装を持つことになります)。
これが良いデザインパターンなのか悪いデザインパターンなのか、参考になるものは見つかりませんでした。少なくとも、C標準で保証されている共通の最初の要素の一貫した順序とパディングにのみ依存しており、厳密なエイリアシングルールに違反していないようです(私が見る限り)。もちろん、C でオブジェクト指向のパターンがあることは知っていますが、この特定のパターンが使用されていることはわかりませんでした。
これは受け入れられますか?そのようなパターンも使用されましたか?(何も見つかりませんでした)
理解を容易にするために、以下に 3 つのソース ファイルの実際の例を示します。
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;
}
おそらく、インターフェイスは実装者に別のヘッダー ファイルを提供し、関数ポインターを含む構造体 head の定義を提供する必要があります。多くのメソッドを持つクラスのオブジェクト サイズを最小化するために、それらを含むクラス構造を指すことさえあるかもしれません。