我有两个链接列表:-
struct Struct_A_s {
int a;
struct Struct_A_s *next;
}Struct_A;
struct Struct_B_s {
int a;
int b;
int c;
int d;
struct Struct_B_s *next;
}Struct_B;
我已经有几个在 Struct_A 上运行的函数。 诸如此类的事情:
“Add_tail (Struct_A *)”、“Remove_tail(Struct_B *)”、“Add_node(Struct_A *,int pos)、Add_head 等已就位。
对我来说,我的要求是修改现有的函数,以便它们可以同时对 Struct_A 和 Struct_B 进行操作。
在 C 中,有没有一种方法可以传递 void 指针(或类似的东西)并编写一些通用代码来同时处理 Struct_A 和 Struct_B。 代码大小是这里的一个大问题。目前我看到的唯一选择是从头开始重写 Struct_B 的所有代码(链表操作)。
最佳答案
有几种方法可以解决这个问题。我确信其他人比我建议的更熟练。
- 选项 A:传递一个 void 指针和某种数据类型指示,然后进行转换。
- 选项 B:将两个指针组合成一个并集并传递。
- 选项 C:将类型和 union 组合成一个结构并传递
- 选项 D:使用更受尊重的 union 替代方案
一些示例代码...
enum DataType { TYPE_1, TYPE_2 };
struct Type1 { ... };
struct Type2 { ... };
union Data
{
void* addr;
struct Type1* type1;
struct Type2* type2;
}
struct Object
{
DataType type;
union Data data;
}
struct Thing
{
DataType type;
void* data;
}
void someFunc1( void* data, DataType type )
{
switch( type )
{
case TYPE_1:
{
struct Type1* type1 = (struct Type1*)data;
...
break;
}
case TYPE_2:
{
struct Type2* type2 = (struct Type2*)data;
...
break;
}
}
}
void someFunc2( union Data* data, DataType type )
{
switch( type )
{
case TYPE_1:
{
struct Type1* type1 = data->type1;
...
break;
}
case TYPE_2:
{
struct Type2* type2 = data->type2;
...
break;
}
}
}
void someFunc3( struct Object* object )
{
switch( object->type )
{
case TYPE_1:
{
struct Type1* type1 = object->data.type1;
...
break;
}
case TYPE_2:
{
struct Type2* type2 = object->data.type2;
...
break;
}
}
}
void someFunc4( struct Thing* thing )
{
switch( thing->type )
{
case TYPE_1:
{
struct Type1* type1 = (struct Type1*)thing->data;
...
break;
}
case TYPE_2:
{
struct Type2* type2 = (struct Type2*)thing->data;
...
break;
}
}
}
换个角度看...如果你有一个只需要 a
的方法,那么你可以做这样的事情...
void myFunc( int a ) { ... };
void someFunc3( struct Object* object )
{
myFunc( object->type == TYPE_1 ? object->data.type1->a : object->data.type2->a );
}
更好的是...修改函数以接受对象并仅在底部进行区分...
void myFunc( struct Object* object )
{
int* a;
switch( object->type )
{
case TYPE_1:
{
a = &object->data.type1->a
break;
}
case TYPE_2:
{
a = &object->data.type2->a;
break;
}
default:
{
abort();
}
}
// do work with a as though it were passed in as a pointer to int
if( object->type == TYPE_2 )
{
// do additional work with the b, c, d elements, etc.
}
}
关于c - 单一函数可处理两种类型的链表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16426577/