2014-02-11 129 views
1

我正在做一個小遊戲,我有一個結構,包含精靈信息。該精靈的成員之一可以是SDL_Texture或其他任何類型的成員。我正在編寫這個結構作爲支持多種平臺的方法。我的整個代碼引用這個結構,並且根據它運行的平臺,「紋理」成員可以是任何類型:SDL_Texture,kgl_Tex,byte []等。柔性構件類型的結構?

如何創建一個具有靈活性的結構成員類型並允許我的代碼支持多種平臺特定的類型?順便說一句,我對ANSI C.

下面是一個更加「真實」的例子就是我在尋找:

typedef struct 
{ 
    int frames; 
    int x; 
    int y; 
    ? *texture; 
} Sprite; 

void load_sprite() 
{ 
    Sprite sprite; 

    sprite.texture = load_sdl_sprite('test.png'); // This will return a SDL_Texture* 
    sprite.texture = load_kgl_sprite('test.png'); // This will return a kgl_tex* 
    sprite.texture = load_lib_sprite('test.png'); // This will return a sprite_t* 
} 
+0

不,它不是一個可變長度數組,我正在尋找:它將不同類型的變量分配給同一個成員。像泛型一樣,使用C++。 – vinnylinux

+0

你可以試試'union' – nullpotent

+0

我用更簡潔明瞭的例子更新了我的問題。 – vinnylinux

回答

1

在你的結構一個void*創建變量類型和跟蹤哪些實際類型取決於您的平臺。

然後根據需要在每個平臺上創建訪問函數,將指針轉換爲需要的類型。

typedef struct 
{ 
    int frames; 
    int x; 
    int y; 
    void* texture; 
} Sprite; 


void load_sprite() 
{ 
    Sprite sprite; 

    sprite.texture = load_sdl_sprite('test.png'); // This will return a SDL_Texture* 
    sprite.texture = load_kgl_sprite('test.png'); // This will return a kgl_tex* 
    sprite.texture = load_lib_sprite('test.png'); // This will return a sprite_t* 
} 

因爲質地類型void*你可以指定你喜歡的任何指針類型。由您來跟蹤它實際指向的內容。

或者使用大量的#ifdef語句來屏蔽基於平臺的實際類型。

0

可能是你有一個void指針字段,它包含實際紋理數據/結構的地址; 和另一個int字段中包含「類型」代碼,指示紋理的類型。

3

如果只有一個值,這基本上「指針」,我可能會被混淆該指針解決這個問題,用不同的別名爲每個平臺:

#if defined WITH_SDL 
#include SDL-specific headers 
typedef SDL_Surface Texture; 
#elif defined WITH_KGL 
#include KGL-specific headers 
typedef kgl_tex Texture; 
#elif defined WITH_LIB 
#include LIB-specific headers 
typedef sprite_t Texture; 
#else 
#error Undefined platform, no Texture representation. 
#endif 

typedef struct 
{ 
    int frames; 
    int x; 
    int y; 
    Texture *texture; 
} Sprite; 

這樣做的(史詩)獲勝保持平臺的首選本地類型。它也避免了在不爲他們建設時提及其他平臺的類型,這可能是一個巨大的勝利。

typedef圖層可能會引入警告,但分配例如將類型SDL_Surface *的值寫入Texture *類型的指針中。如果發生這種情況,它可能只是typedef void Texture,並完成它。

你應該把上面的一些應用程序特定的標題(sprite.h)或其他東西,然後#include,在所有文件,需要創建一個Texture。您的示例代碼不太可信;你永遠不會有三次調用不同的API,它們會像這樣一個接一個地做同樣的事情。通常你會使用像上面這樣的預處理符號,或者例如sprite-sdl.c,sprite-kgl.c等。它在那些實現Sprite功能的文件中,您將需要上述的#include

我添加了API特定的包含作爲佔位符,這是做到這一點的一種方法。

+0

現在,這是優雅的。謝謝! :D – vinnylinux

+0

雖然我不確定是否得到了typedef void Texture。我應該什麼時候這樣做? func調用之前? – vinnylinux

+0

@vinnylinux如果使用'typedef'別名(這將需要強制轉換)有問題,'typedef void Texture;'是*不同*解決方案。我沒有嘗試,我不確定。 Csat是壞的,所以如果你需要演員,不妨先用'void *'開始,這是我的想法。 – unwind

0

保留所有的可能性(但它是一個錯誤的觀念,以保持它),另一種方法是使結構與類型,以及工會:

enum Texture_type 
{ 
    type_sdl, 
    type_kgl, 
    type_sprite_t 
}; 

struct Texture 
{ 
    enum Texture_type type; 
    union all 
    { 
     SDL_Surface* Tsdl;   
     kgl_Tex* Tkgl; 
     sprite_t* Tspr; 
    } 
} 

結構紋理可以持有任何你的紋理的。 分配它:填充類型,然後將好指針填充到聯合中。 刪除它:你打開類型調用SDL_FreeSurface或其他