C 枚举是整数。该语言只是提供了一些语法来进行名称到 int 的替换(以及编译器可以强制执行的一些其他项目)。
如果你想要一个类似 Java 的枚举,你需要创建一堆全局对象。由于 C 缺乏对 Java 枚举合约的强制执行,因此您需要尽最大努力实现它们。
因此,这在两个方面使问题复杂化。现在您需要模拟一个对象并模拟枚举(如果您想要在 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;
}
现在,如果你想要封装,你可以将结构分成两部分,一是暴露的,一是隐藏的。第一种技术是只暴露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”方法。有一个警告。在 C 中传递“this”指针并没有真正的好方法,因为成员函数缺乏“知道”它们在结构中的能力,以及“知道”该结构从哪里开始的能力。是的,有一些变通方法,但它们开始花费更多的时间和金钱。我通常只是不打扰,这使得这样的代码很常见。
result* myresult;
(*myresult).getValue(myresult);
虽然我希望您喜欢更深层次的表面处理,但您应该比成员函数更早停止。也许我应该比多态的实现更早停止:)