抽象数据类型的本质是,客户机代码具有如下类型的值的结构没有任何的洞察力 - 这也意味着任何功能处理这样的值的实施是不透明的。
在你的例子中,这意味着你不要在头文件中定义struct
,而只是使用前向声明。对于遍历,你也可能想要定义一个同样不透明的迭代器类型,例如
struct symtable;
struct symtable_iterator;
...然后是与该表一起工作的函数的集合,例如,
/* Create symtable, destroy it, insert values. */
void symtable_alloc(struct symtable **table);
void symtable_free(struct symtable *table);
void symtable_insert(struct symtable *table, const char *key, void *value);
/* Create symtable iterator, destroy it, access key/value. */
void symtable_iterator_alloc(struct symtable *table, struct symtable_iterator **it);
void symtable_iterator_free(struct symtable_iterator *it);
bool symtable_iterator_next(struct symtable_iterator **it);
const char *symtable_iterator_key(struct symtable_iterator *it);
void *symtable_iterator_value(struct symtable_iterator *it);
这就是你应该放入头文件。在实现(.c
)文件中,实际上可以定义结构及其字段 - 但该代码对客户端是隐藏的。
你可以使用他们喜欢
struct symtable *table;
symtable_alloc(&table);
symtable_insert(table, "one", "eins");
symtable_insert(table, "two", "zwei");
symtable_insert(table, "three", "drei");
struct symtable_iterator *it;
symtable_iterator_alloc(table, &it);
while (symtable_iterator_next(&it)) {
printf("%s: %s\n", symtable_iterator_key(it), symtable_iterator_value(it));
}
symtable_iterator_free(it);
symtable_free(table);
注意如何设定的功能明确定义了数据结构的API,但实际类型是抽象的 - 有没有信息这给走表的实现,例如无论是链表还是哈希表或别的东西。
谢谢你的解释!我对头文件/源文件已经很熟悉,但是你对我的阐述很不错。你能评论我的结构,或者可能会破坏'typedef struct SymTable * SymTable_T'语句吗?我知道'struct SymTable'是结构本身,但指针指向什么? –