2

私はこのように定義された構造体を持っています:

struct GameState {
    int score;
    int moves;
    bool won;

    void *metadata;
};
typedef struct GameState GameState;

メタデータポインタは、実行時に決定されたタイプの別の構造体を指します。たとえば、次のようになります。

struct KlondikeMetadata{
    bool draw3;
    int drawcount;
};
typedef struct KlondikeMetadata KlondikeMetadata;

または多分:

struct FreeCellMetadata{
    int reserveCells;
};
typedef struct FreeCellMetadata FreeCellMetadata;

使用される実際のメタデータ構造体は、ユーザーがプレイしているゲームによって異なります。ユーザーがどのゲームをプレイしているかがわかっているので、99%の確率でこれは問題になりません。しかし、私がこれを知らない(そして知らない)場合があります。

私の質問は、実行時に正しいメタデータタイプを決定または指定する方法はありますか?

たとえば、メタデータ値がKlondikeMetadata型であることを示すプロパティをGameState構造体に追加し、それを使用してメタデータをその型にキャストできれば、私は黄金になると思います。これを行う方法はありますか?Cで実行時に型を指定して変数をキャストする方法はありますか?

4

1 に答える 1

7

自分でエンコードする必要があります。

最も簡単な解決策は、列挙を宣言することです。

typedef enum {
 GameType_Klondike,
 GameType_FreeCell,
} GameType;

次に、そのタイプのフィールドをポインターの前に追加します。

GameType game_type;
void     *metadata;

もちろん、これは、タイプを記憶するために、初期化するときにフィールドを設定する必要があることを意味します。game_typemetadata

また、少しオブジェクト指向にしてGameType、メタデータの一部にすることもできます。

struct Metadata {
 GameType gametype;
};

struct FreeCellMetadata {
 struct Metadata meta;
 /* rest of fields here */
};

struct KlondikeMetadata {
 struct Metadata meta;
 /* rest of fields here */
};

次に、にキャストし、ポインタを適切なタイプにキャストする前にフィールドvoid *struct Metadata *検査できます。gametype

ボーナスポイントについては、ユニオンを使用してください。

struct Metadata {
 GameType type;
 union {
 struct KlondikeMetadata klondike;
 struct FreecellMetadata freecellL;
 } game;
};

繰り返しますが、もちろん、これにはデータを維持する必要があります。つまり、初期化するときは、そのフィールドstruct KlondikeMetadataを設定することを忘れないでください。gametype

于 2013-03-19T14:01:04.737 に答える