是的,你可以使用这样的原型:
void foo(char type, void *data);
Run Code Online (Sandbox Code Playgroud)
使用类型告诉函数将数据用作哪个结构,就可以了。
struct c *prepareStructC(void);
//...
struct c *toto = prepareStructC();
foo('c', toto);
//...
void foo(char type, void *data)
{
int x, y;
switch (type)
{
case 'c':
x = ((struct c*)data)->x;
y = ((struct c*)data)->y;
break;
//...
}
//...
}
Run Code Online (Sandbox Code Playgroud)
第二个选项,如果您想避免 switch/case,并且能够在之后添加更多结构类型,而不需要进化 foo,您可以确保所有结构都以必要的数据开头,始终以相同的顺序、相同的类型。这样你就可以从 C++ 中创建类似“接口”的东西,并使用该类型的抽象版本:
struct abstract
{
int x;
int y;
int radius;
}
struct a
{
struct abstract abs;
//... other data ...
}
struct b
{
struct abstract abs;
//... other data ...
}
struct c
{
struct abstract abs;
//... other data ...
}
//Two choices : either you have:
void foo(void *data)
{
int x,y,r;
x = ((struct abstract*)data)->x;
y = ((struct abstract*)data)->y;
r = ((struct abstract*)data)->radius;
//...
}
//OR Smarter way:
void foo2(struct abstract *data)
{
int x,y,r;
x = data->x;
y = data->y;
r = data->radius;
}
//Calling foo2 with:
struct a *sa = prepareStructA();
struct b *sb = prepareStructB();
struct c *sc = prepareStructC();
foo2(sa->abs);
foo2(sb->abs);
foo2(sc->abs);
Run Code Online (Sandbox Code Playgroud)
第二种方法的第二部分允许您更加灵活,分解子类型中的特定信息,使您能够将该abs部分放置在结构体 a/b/c 内的任何位置,并且更好地遵循结构体的单一用途原则(在结构体中包含坐标、半径和其他内容并不总是最好的。)
| 归档时间: |
|
| 查看次数: |
3274 次 |
| 最近记录: |