2

私は、イベントが文字列と整数からのキーで表されるイベントマネージャーに取り組んでいます。つまり、イベントはクラスまたはオブジェクトによって表されません。このようにして、コンポーネントはイベントを介して通信できますが、独立した状態を保ちます。イベントを登録する必要はありませんが、誰もがイベントを聞くか、イベントを発生させることができるということは、イベントマネージャーにとって重要なガイドラインです。

(イベントキーの整数部分は、コンテンツの同じイベントのフェーズをグループ化するためのものです。たとえば、手榴弾は、投擲、飛行、着陸、爆発のイベントをトリガーします。これらは、「手榴弾」0、「手榴弾」1、..として表す必要があります。 。「手榴弾」4.)

オプションで、イベントには、イベントを参照するデータを送信するためのvoidポインターを含めることができます。それはクラッシュの速度、殺されたプレイヤーのIDである可能性があります。

すべてのコンポーネントには、という名前のイベントnamagerへのポインタが含まれていますEvent。メソッドを登録したり、イベントに委任したりしたいと思います。

// ideally registering for an event would look like that
Event.Listen("eventname", 0, this->Method);
Event.Listen("eventname", 0, [](){ ... });

// receiving data is optional
Event.Listen("eventname", 0, [](void* Data){ ... });

発砲イベントは理想的には同様に機能します。

Event.Fire("eventname", 0);
Event.Fire("eventname", 0, Data);

// fires events "eventname" 0, "eventname" 1, ... "eventname" 5
Event.FireRange("eventname", 0, 5);

イベントマネージャは、イベントのリストを保持します。これは、イベントキーと登録されているすべての関数のベクトルを意味します。

typedef unordered_map<pair<string, int>, vector<function>> ListEvent;
ListEvent List;

ベクターは、特定のイベントに登録されているすべての関数を格納します。関数ポインタ、メンバー関数ポインタなどを使ってみstd::functionました。しかし、私が望むように何も機能しませんでした。このイベントマネージャーに関連する私の質問のいくつかを次に示します。2つのstd::functionが等しいかどうかを確認し、関数ポインターを任意のメンバー関数に格納し、オブジェクトの型が特定のクラスから継承されているかどうかを確認します。

リスニング関数がそのクラスのメンバーにアクセスできることが重要です。そして、ラムダ関数を1行のコードで登録したいと思います。

そのようなイベントマネージャーのコーディングに取り組むためのアイデアやテクニックはありますか?

私は自分の問題を一般的な方法で提示しようとしましたが、追加の説明やコードが必要な場合は、遠慮なくコメントしてください。

4

1 に答える 1

2

簡単に作業できるスケッチは次のとおりです。

#include <vector>
#include <functional>
#include <iostream>

typedef std::function<void(int param)> callback;

struct Event {
  std::vector<callback> subs;//criptions  

  void subscribe(callback cb) { subs.push_back(cb); }
  void fire(int param = 0) { for(callback& cb : subs) cb(param); }
};

void some_free_func(int param) { std::cout << "some_free_func got signal" << std::endl; }

int main(int argc, char* argv[])
{
  Event evt0; 
  evt0.subscribe(some_free_func);

  evt0.subscribe([](int p) { std::cout << "some_lambda got signal" << std::endl; } );

  evt0.fire();
    return 0;
}

概念的には、大まかに必要なことを実行しますが、ここで所有権ポリシーについて考える必要があります。上記の私の質問を確認してください。

編集:所有権が問題ではないと言うなら、これはうまくいくかもしれません:

void my_object::firstCry() { 
   evt0.subscribe([=](int p) { this->got_signal(p); }); // inst/method thunk 
}

void my_object::got_signal(int param) {...}
于 2012-10-20T17:47:03.997 に答える