今更オブジェクト指向,今更C++ということではあるが,現在C++を強烈なオブジェクト指向言語として利用中.あくまで一例,tipsとして.コードは一番下にあります.
テンプレの使用方法
Sampleを何かで置換してやるだけで動きます。
イベント関数の引数を変えたいときはinterface
のOnSampleHandle
の引数,SampleEventHandler
のCallonSampleEventHandler
の実装で呼び出す部分の引数をそれぞれほしいものに変えればよいです。
イベントを作成したいときは,初めにEventHandlerを用意し,欲しいイベントのprivateリストを作成します。
続いて,欲しい関数を作成するか,または実装したいクラスにインターフェースを継承させます。関数を作成した場合は,その関数f
を引数にしてSampleEventHandler::Instance()->addOnSampleEvent(f)
と登録してください。
イベントは,SampleEventHandler::Instance()->CallonSampleEventHandler(vargs)
とすれば発火します。
解説
イベントハンドラの1つ目のリストは直接関数を,2つ目の関数はインターフェースの実装として登録する場合です。
直接関数は,関数をダイレクトにアタッチすることによって登録されます。この時,クラスのメンバ関数やstd::functionは禁止です。構造が異なります。
インターフェースの実装による登録は,テンプレ通りにすれば自動的に登録されます。ただし,少しオーバーヘッドがでかい恐れがあります。
本質はaddふにゃふにゃとCallon,vector2つなので,それらを内包させられる場合は一つのイベントハンドラで複数のイベントを管理できます。
これを利用して一つのイベントを複数のイベントに分解するなどの応用例があります。その場合は,Callon関数で自分の状態から適切な引数を与えるように呼び出せばよいです。
interface
typedef void (OnSampleHandle)(int var);
class ISampleListener
{
public:
ISampleListener();
virtual ~ISampleListener() = default;
virtual void onFired(int var) = 0;
private:
void registerListener();
};
インターフェースの実装
ISampleListener::ISampleListener()
{
this->registerListener();
}
void ISampleListener::registerListener()
{
SampleEventHandler::Instance()->addSampleListener(std::unique_ptr<std::remove_reference<decltype(*this)>::type>(this));
}
EventHandler
class SampleEventHandler : public Singleton
{
public:
SampleEventHandler();
void CallonSampleEventHandler(int var);
void addOnSampleEvent(OnSampleHandle event);
void addSampleEvent(std::shared_ptr<ISampleListener> listener);
private:
v2 var;
std::vector<ISampleListener*> _onSample = {};
std::vector<std::shared_ptr<ISampleListener>> _onpSample = {};
};
ハンドラの実装
#include <omp.h>
void SampleEventHandler::CallonSampleEventHandler(int var)
{
#pragma omp parallel for
for (auto fn : this->_onSample)
{
fn(var);
}
#pragma omp parallel for
for (auto p : this->_onpSample)
{
p->onFired(var);
}
}
}
void SampleEventHandler::addOnSampleEvent(OnSampleHandle event)
{
this->_onSample.push_back(event);
}
void SampleEventHandler::addSampleEvent(std::shared_ptr<ISampleListener> listener)
{
this->_onpSample.push_back(std::move(listener));
}