刚刚在C中完成了小链表,并意识到我遇到了问题。 C没有模板参数,所以在文件的开头,我声明了我的数据类型列表,如:
typedef int LData;
到目前为止一切顺利,但我不能在一个程序中将这个链表用于2个(或更多个)不同的数据类型。
我可以将LData
定义为void*
,并根据上下文手动将其转换为特定的数据类型。但我想知道是否有更优雅的解决方案?
答案 0 :(得分:2)
将LData
类型定义为void*
。链表的用户必须知道它包含哪种数据,因此只要他们将数据输入或输出,他们就可以在void*
之间进行转换。
答案 1 :(得分:1)
union
是为此目的而发明的,虽然它不是一个非常安全的结构。
答案 2 :(得分:0)
或者,使用不透明指针idiom:
struct datum;
typedef struct datum datum;
typedef datum *LData;
struct datum {
int whatever;
};
答案 3 :(得分:0)
你可以有一堆#defines定义存储在“link”中的类型吗?
即
#define TYPE_INT 0
#define TYPE_FLOAT 1
// etc
然后将每个条目定义为:
struct LinkedListLink
{
int type;
LData data;
};
现在通过检查“类型”,您知道添加了哪种数据(假设您在设置LinkedListLink结构时已正确设置它)。
答案 4 :(得分:0)
当我想使用一组通用链表(或我的情况下,队列)代码时,我将链表指针嵌入到我想要使用它的更大结构中。然后在将参数传递给链表函数时使用链接字段名称。并且有一个函数可以从链接列表指针转换为更大的结构指针,以便从链接列表中获取指针。类似于你在下面看到的代码。
这个习惯用法并没有给你C ++的类型安全性,但是代码非常干净,而且转换只是局限于几个函数。
// some representative bits of my linked list API
//
typedef void* PLINK;
extern PLINK LLAddToList(PLINK head, PLINK new);
extern PLINK LLNextItem(PLINK current);
// the structure I want to use it with
typedef struct _foo {
PLINK pLink;
int data1;
int data2;
} FOO;
// to allow for the link pointers to be some other than the first field
// we use this to go from link pointer to structure pointer.
FOO * FooFromPLink(PLINK current) {
return (FOO *)((char *)¤t - FIELD_OFFSET(FOO, pLink));
}
void MyFunction()
{
// this idiom to use the linklist code with a FOO struct
//
FOO * pfoo = // allocate and initialize a foo
LLAddToList(head, &pfoo->pLink);
// this idiom to traverse a list of FOOs, etc.
//
PLINK next = LLNextItem(head);
while (next)
{
pfoo = FooFromPLink(next);
// operate on foo.
next = LLNextItem(next);
}
}