1

ゲームで使用する非常に単純なイベント システムを作成しようとしています。次のような EventManager クラスがあります。

typedef std::function<void(IEvent* event)> CallbackType;

class EventManager
{
public:
    void AddListener(const std::string eventName, IEventListener* listener)
    {
        CallbackType callback = std::bind(&IEventListener::HandleEvent, listener, std::placeholders::_1);

        listeners[eventName].push_back(callback);
    }

    void AddListener(const std::string eventName, CallbackType callback)
    {
        // ...
    }

    void TriggerEvent(IEvent* event)
    {
        for (CallbackType callback : listeners[event->GetName()])
        {
            callback(event);
        }
    }
private:
    std::map<std::string, std::vector<CallbackType>> listeners;
}

最初の AddListener 関数は完全に機能します。TriggerEvent 関数は、IEventListener インターフェイスを拡張する各クラスによって実装される HandleEvent 関数を呼び出します。

2 番目の AddListener 関数にコールバックを渡せるようにしたいです。このコールバックは、以前と同様に TriggerEvent 関数で呼び出されます。std::bind を使用して構築されたコールバックを渡すことができ、これは機能します。例えば:

eventManager->AddListener("WindowResize", std::bind(&MyClass::MemberFunction, this, std::placeholders::_1));

ここで、MyClass は IEventListener インターフェイスを拡張します。ただし、代わりに単純な関数ポインターを渡すことができるようにしたいと思います。

eventManager->AddListener("WindowResize", this, &MyClass::MemberFunction);

これは可能ですか?

編集

興味のある人のために、私はいくつかのマクロを書きました。

#define MEMBER_CALLBACK(funPtr) \
std::bind(&funPtr, this, std::placeholders::_1)

#define MEMBER_CALLBACK_WITH_INSTANCE(funPtr, instancePtr) \
std::bind(&funPtr, instancePtr, std::placeholders::_1)

これで、次の方法でイベントをサブスクライブできます。

eventManager->AddListener("EventName", MEMBER_CALLBACK(MyClass::MemberFunction));
4

1 に答える 1

2

単純な関数ではないため、単純な関数ポインターを渡すことはできませんMyClass::MemberFunction。のstd::bind()インスタンスをMyClassメンバー関数への参照に関連付けるために機能します。その情報がなければ、メンバー関数はインスタンスのデータにアクセスできません。

于 2013-06-12T06:11:24.167 に答える