0

次のコードスニペットのポインター関数宣言を使用すると、構造体内の各関数の名前を変更できます。これは単なる架空のものであるため、名前はまだ重要ではありません。

ヘッダーファイル

typedef struct
{
    bool (*enabled)(uint32_void);
    void (*start)(uint32_t);
    void (*stop)(uint32_t);
    bool (*expired)(void);
} battle_star_gallactica;

Cファイル

static bool Battle_v0_enabled (void) { ... }
static void Battle_v0_start (uint32_t) { ... }
static void Battle_v0_stop (uint32_t) { ... }
static bool Battle_v0_stop (void) { ... }

const battle_star_gallactica battle_v0 =
{
    enabled,
    start,
    stop,
    expired
};
...

1つの使用例

battle_v0.start(1000);

Cファイルスニペットは他のバージョンでも繰り返されます(たとえば、v0ではなくv1またはv2)。

これはどのように作動しますか?

編集

修正されたコード:

ヘッダーファイル

typedef struct
{
    bool (*enabled)(uint32_void);
    void (*start)(uint32_t);
    void (*stop)(uint32_t);
    bool (*expired)(void);
} battle_star_gallactica;

extern const battle_star_gallactica battle_v0;
extern const battle_star_gallactica battle_v1;
...

Cファイル

static bool Battle_v0_enabled (void) { ... }
static void Battle_v0_start (uint32_t val) { ... }
static void Battle_v0_stop (uint32_t val) { ... }
static bool Battle_v0_expired (void) { ... }

const battle_star_gallactica battle_v0 =
{
    Battle_v0_enabled,
    Battle_v0_start,
    Battle_v0_stop,
    Battle_v0_expired
};
...

1つの使用例

battle_v0.start(1000);
4

3 に答える 3

2

はい。しかし、いくつかの問題があります。

1)Battle_v0_stopは2回定義されています2)初期化するときbattle_v0は、値の前にプレフィックスを付ける必要がありますBattle_v0_

その後、次のことができます。

battle_v0.enabled()

しかし、私はcurrnetを持っていて battle star galactic、それを使用します:

const battle_star_gallactica bsg = battle_v0;
bgs.enabled()
于 2013-01-27T00:18:52.720 に答える
1

enabled、、などの名前の関数はありませんstart。関数ポインタを使用してオブジェクトを初期化するときは、実際の関数名(つまり)へのポインタを渡しますBattle_v0_start。とはいえ、タイプが一致しないことに注意することが重要です。Battle_v0_start(uint32_t)ではなく、である必要がありvoidます。

ただし、適切に初期化された後は、を呼び出すだけで済みますyour_obj.your_struct_function_name(your_arguments, ...)。あなたの場合battle_v0.start(1000)は呼び出しますBattle_v0_start(この関数をポインタに渡した場合)。これは、他のほとんどのポインタタイプと同じように考えることができます。

于 2013-01-27T00:17:43.713 に答える
1

次のような各関数ポインタにターゲット関数を割り当てる必要があります。

battle_v0.enabled = Battle_V0_enabled;
battle_v0.start   = Battle_V0_start;
// etc.

また

const battle_star_galactica battle_v0 = {
    Battle_V0_enabled,
    Battle_V0_start,
    Battle_V0_stop,
    Battle_V0_expired
};

次に、ポインタを介して関数を呼び出すことができます。

battle_v0.start(1000);  // or battle_v0.(*start)(1000)

Battle_V0_start1000の値で関数を呼び出します。

関数のシグネチャ(戻り値の型と引数の数/型)は一致する必要があることに注意してください。たとえば、start型の引数を取るために関数ポインタを宣言しますuint32_tが、引数はBattle_V0_start取りません。これらのいずれかが一致するように変更する必要があります。

void Battle_V0_start(uint32_t val) { ... }
于 2013-01-27T00:46:44.780 に答える