我有一個函數使用OpenGL繪製一個圓,我想傳遞一個包含x和y座標以及半徑的結構。問題是這個函數必須與3個不同的結構一起使用,所有結構都包含繪圖函數不使用的座標,半徑和其他一些東西。C:爲一個函數參數發送不同的結構
是否有某種方法只有一個參數爲3個不同的結構(一次只發送一個參數)。
我希望我已經足夠精確。 PS:函數必須是「抽象的」。
我有一個函數使用OpenGL繪製一個圓,我想傳遞一個包含x和y座標以及半徑的結構。問題是這個函數必須與3個不同的結構一起使用,所有結構都包含繪圖函數不使用的座標,半徑和其他一些東西。C:爲一個函數參數發送不同的結構
是否有某種方法只有一個參數爲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;
//...
}
//...
}
第二種選擇,如果你想避免一個開關/箱,並能夠在事後添加更多的結構類型,沒有演變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
部分放在struct a/b/c的任何地方,並且在結構單一目的的原則中更好(座標和半徑爲和其他東西並不總是最好的。)
僅當函數接受void*
作爲參數,然後您將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
}
}
然而,這樣做你會)需要通過另一種說法,表示正在鑄造到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);
}
你是對的,枚舉比一個普通的「char」更好,我的第一個方法更加骯髒^^「 – Eregrith 2012-04-18 15:42:29
同意,但是你用一個相同的數據」簽名「開始單獨的結構是很好的一點,類型系統和(理論上)隨着時間的推移對主要功能的更改較少。 – 2012-04-18 15:47:07
+1用更聰明的方式第二個選項:這正是OO是如何在C. – mouviciel 2012-04-18 15:45:38
謝謝你們實現,我在一個結構包含一個struct的打算。 – DennisVDB 2012-04-18 16:55:04