だから、私はウリに反対する傾向があります。
オブザーバー パターンを実装している場合は、次のように言えます。
「オブジェクトXがYを実行するとき、コードZを実行したい」.
純粋に抽象クラスに基づくアプローチを採用することは、最善の方法ではありません。すべてのイベント ハンドラーに個別のクラス (特に C++) を要求するのはやり過ぎです。あなたがJavaから来ているなら、それは彼らがすべてを行う方法です. ただし、Java には、匿名クラスと「インスタンス」メンバー クラスという 2 つの機能があります。これにより、同じクラス内の複数のイベントに対して複数のハンドラーを定義できます。メソッドの前に「class {」を付ける必要がありますが、それは可能です。
C++ には、無名クラスも「インスタンス」メンバー クラスもありません。これにより、状態を共有する必要がある複数のハンドラーがある場合、イベントに抽象クラスを使用するのが非常に面倒になります。クロージャの生成に相当することを手動で行う必要があり、これは非常にすぐにイライラする可能性があります。
.NET はイベント処理にデリゲートを使用しますが、これは基本的にタイプ セーフな関数ポインターです。これらは、イベントを処理するためのコードを非常に簡単にします。ただし、C++ の関数ポインターとは異なり、デリゲートはメンバー関数ポインターと静的関数ポインターを統合します。基本的に、静的関数ポインターのように見える関数ポインターを残して、任意のメンバー関数の「this」パラメーターをカリー化できます。これは、イベントを処理するオブジェクトのタイプがイベント「インターフェース」の一部ではないことを意味します。それはそれを非常に柔軟にします。
「this」型は最終的に関数ポインター型の一部になるため、C++ メンバー関数ポインターを直接使用してこれを行うことはできません。したがって、ハンドラーは現在のクラス内にのみ表示されるように制限されます。
C++ の最適なソリューションは、2 つのハイブリッドです。必要なのは、次のような汎用インターフェイスです。
class EventHandler
{
public:
virtual void Handle() = 0;
};
そして、このようなメンバー関数の実装
template <class T>
class MemberFuncEventHandler : public EventHandler
{
public:
MemberFuncEventHandler(T * pThis, void (T::*pFunc)()) : m_pThis(pThis), m_pFunc(pFunc)
{
}
void Handle()
{
(m_pThis->*m_pFunc)();
}
private:
T* m_pThis;
void (T::*m_pFunc)();
};
template <class T>
EventHandler * Handler(T * pThis, void (T::*pFunc)())
{
return new MemberFuncEventHandler<T>(pThis, pFunc);
}
同様に、静的メソッドのハンドラー クラスを定義することもできます。次に、次のようなことができます。
Handlers += Handler(obj, &(c1::foo));
Handlers += Handler(obj, &(c2::bar));
Handlers += Handler(blaa); // for static methods...