C 列挙型は int です。この言語は、name から int への置換を行うためのいくつかの構文を提供するだけです (およびコンパイラーが強制できる他のいくつかの項目)。
Java のような列挙型が必要な場合は、一連のグローバル オブジェクトを作成する必要があります。C では Java 列挙型コントラクトが強制されていないため、可能な限りそれらを実装する必要があります。
したがって、これは 2 つの点で問題を複雑にします。ここで、オブジェクトをシミュレートし、列挙型をシミュレートする必要があります (c で Java のような列挙型が必要な場合)。
オブジェクトをシミュレートするには、うまく機能するテクニックがいくつかあります。重要なのは、必要な機能だけを実装するのを早期にやめることです。追加する機能が増えるほど、次のことが難しくなります。
typedef struct tag_result {
int enum_value;
char* enum_name;
} result;
result* getEnumByValue(int index);
result* getEnumByName(char* name);
そして.c
ファイルに
// resize to match entries
int enum_limit = 5;
result enums[enum_limit];
// it is your responsibility to not duplicate values.
enums[0].enum_value = 0;
enums[0].enum_name = "invalid_argument";
enums[1].enum_value = 1;
enums[1].enum_name = "no_memory";
result* getEnumByName(char* name) {
int index;
for (index = 0; index < enum_limit; index++) {
if (strcmp(enums[index].enum_name, name)) {
return enums[index];
}
}
return 0;
}
result* getEnumByValue(int value) {
int index;
for (index = 0; index < enum_limit; index++) {
if (enums[index].enum_value == value) {
return enums[index];
}
}
return 0;
}
ここで、カプセル化が必要な場合は、構造体を 2 つの部分 (1 つは公開、もう 1 つは非表示) に分割できます。最初の手法は、 のみを公開しtypedef struct s_result result
、構造体のレイアウトを で定義できるようにすること.h
です。最初は少しトリッキーですが、インクルードによって何も公開されないことが保証され、.c
ファイルへのフル アクセスが提供されます。この手法を使用する場合は、アクセサー メソッドを追加する必要があります。
int getResultValue(result* item) {
return (*item).enum_value;
}
char* getResultName(result* item) {
return (*item).enum_name;
}
一部の人々はこれをさらに掘り下げ、「パブリック」ヘッダーと「プライベート」ヘッダーがあります。一方の構造体が他方の構造体を参照している (void* ポインターによって隠されている)。アイデアは、「プライベート」ヘッダー ポインターの型を公開しないことでデータを非表示にすることです。当然、ビットをつなぎ合わせるには、配線を理解するコンストラクターが必要です。
result* new_resultEnum(int value, char* name) {
result* newItem = (result*)malloc(sizeof(struct s_result));
(*newItem).private = (p_result*)malloc(sizeof(struct s_p_result));
(*newItem).private.enum_value = value;
(*newItem).private.enum_name = name;
return newItem;
}
このような手法を使用すると、C の関数ポインターを介してメンバー メソッドを簡単に追加できます (ただし、構文は少し難しくなります)。
... added to the constructor above ...
(*newItem).getValue = result_getValue;
「getValue」メソッドを公開します。注意点が 1 つあります。C で "this" ポインターを渡す良い方法は実際にはありません。メンバー関数には、構造内にあることを "認識" する機能と、その構造がどこから始まるかを "認識する" 機能がないためです。はい、回避策はありますが、時間と費用がかかり始めます。私は通常、気にしないだけなので、このようなコードは非常に一般的です。
result* myresult;
(*myresult).getValue(myresult);
表面のより深い傷を気に入っていただければ幸いですが、メンバー関数よりもずっと早く停止する必要があります。そしておそらく、ポリモーフィシムの実装よりもずっと早く停止する必要がありました:)