私は入力システムに取り組んでいます。このシステムでは、特定のキーが押されたときに呼び出される関数をオブジェクトに登録できます。ただし、登録されるメソッドはそのオブジェクトのメンバーであるため、登録関数は次のようになります。
void register(EventType type, Class* object, void (Class::*function)()){ //保存 }
問題は、関数を登録するクラスが常に同じであるとは限らないため、これは機能しません。とにかくこれの周りはありますか?
私は入力システムに取り組んでいます。このシステムでは、特定のキーが押されたときに呼び出される関数をオブジェクトに登録できます。ただし、登録されるメソッドはそのオブジェクトのメンバーであるため、登録関数は次のようになります。
void register(EventType type, Class* object, void (Class::*function)()){ //保存 }
問題は、関数を登録するクラスが常に同じであるとは限らないため、これは機能しません。とにかくこれの周りはありますか?
std::function<void()>コールバックを登録するクラスに格納してから、関数テンプレートregisterメンバー関数を追加できます。
struct Foo
{
template <typename F>
void register(EventType type, F&& fun)
{
// make an std::function<void()> from fun and store
}
};
次に、呼び出し側でClassインスタンスとメンバー関数のバインドを行います。Class
struct Bar { void bar() {} };
void foobar() { std::cout << "foobar!\n"; }
Foo f;
Bar b;
f.register(event1, std::bind(&Bar::bar, b)); // will call b.bar()
f.register(event2, foobar); // will call foobar()
これは、テンプレートと関数ポインターを使用せずに行う方法です。次のようなオブザーバー (コールバック) クラスがあります。
class MyCallback {
public:
virtual void run(int abc)
{
cout << "MyCallback::run(" << abc << ")" << endl;
}
};
次に、オブザーバー クラスを親クラス MyCallback でインスタンス化します。
class Test : public MyCallback
{
public:
void run(int abc)
{
MyCallback::run(abc);
}
};
すべてのオブザーバーを呼び出すクラス:
class Subject
{
vector<MyCallback*> observers;
public:
void reg_observer(MyCallback* cb)
{
observers.push_back(cb);
}
void call_out(int abc)
{
vector<MyCallback*>::iterator it;
for(it=observers.begin();it!=observers.end();it++)
{
(*it)->run(abc);
}
}
};
テストコード:
void testcb()
{
Test ttt;
Subject s;
s.reg_observer(&ttt);
s.call_out(123);
}