我有一个使用 OpenGL 绘制圆的函数,我想向它传递一个包含 x 和 y 坐标以及半径的结构。问题是同一个函数必须与 3 个不同的结构一起使用,它们都包含坐标、半径和绘图函数不使用的其他一些东西。
有没有办法让 3 个不同的结构只有一个参数(一次只发送一个)。
我希望我已经足够精确了。
PS:功能必须是“抽象的”。
是的,您可以使用这样的原型:
void foo(char type, void *data);
使用类型告诉函数将数据用作哪个结构,你很好。
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;
//...
}
//...
}
第二种选择,如果你想避免一个 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);
第二种方法的第二部分让你更灵活,分解子类型中的特定信息,使你可以将abs
部分放在结构 a/b/c 内的任何位置,并且在结构单一用途的原则上更好(在结构中包含坐标、半径和其他东西并不总是最好的。)
仅当函数接受 avoid*
作为参数,然后void*
在取消引用它以访问其中的数据之前将其转换为函数中正确的指针类型。
typedef enum
{
type1, type2, type3
} datatype;
void foo(void* data, datatype type)
{
switch(type)
{
case type1:
// do something with data by casting it to the proper type
break;
// ... other cases here
}
}
但是,通过这样做,您将 a) 需要传递另一个参数,该参数指示在void*
传递之前要转换为的原始类型,并且 b) 您正在放弃类型系统,这几乎不是一个好主意,应该始终避免。
如果您采用这种方法,强烈建议在内部调用函数(采用 )之前创建三个采用正确类型的“包装器”函数void*
。严格约定永远不要直接调用函数void*
;只调用包装器。以这种方式,您仍然可以使用类型系统来帮助解决编译错误。
void bar1(someStruct* data)
{
foo((void*) data, type1);
}
void bar2(someOtherStruct* data)
{
foo((void*) data, type2);
}
void bar3(yetAnotherStruct* data)
{
foo((void*) data, type3);
}