C++ 11を使用して多態性クラスのメンバ関数へのコールバックを格納するマネージャを実装したいと思います。問題は、メンバーが所属するオブジェクトが削除されたり削除されたりする可能性があるため、できるだけシンプルにインターフェイスを作成したい場合はどうすればよいか分かりません。std :: functionとstd :: bindを使用してコールバックを格納し、オブジェクトの削除を処理します。
私は次のことを考えました:オブジェクトにstd::weak_ptr
と会員にstd::function
を保存してください。
class MyBase {
public:
MyBase() {}
virtual ~MyBase() {}
};
//--------------------------------------------------
class MyClass : public MyBase {
public:
MyClass() : MyBase() {}
void myDouble(double val) const { std::cout << "Value is: " << val << std::endl; }
};
//--------------------------------------------------
Class Manager {
public:
void setFunction(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = func;
}
private:
std::pair<std::weak_ptr<MyBase>, std::function<void(double)>> m_function;
};
はこれを使用するには:以下
は動作しているようです
Manager db;
std::shared_ptr<MyClass> myClass = std::make_shared<MyClass>();
db.setFunction(myClass, std::bind(&MyClass::myDouble, myClass, std::placeholders::_1));
今、私は彼が唯一の呼び出す必要があるように、利用者からstd::bind
一部を非表示にする:
db.setFunction(myClass, &MyClass::myDouble);
私のマネージャー機能では、ほとんど以下の作業をしたいと考えています。
void setFunc2(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = std::bind(func, base, std::placeholders::_1);
}
しかし、上記のエラーを与える:
error: no match for 'operator=' (operand types are 'std::function<void(double)>' and
'std::_Bind_helper<false, std::function<void(double)>&, std::weak_ptr<MyBase>&, const std::_Placeholder<1>&>::type {aka std::_Bind<std::function<void(double)>(std::weak_ptr<MyBase>, std::_Placeholder<1>)>}')
m_function.second = std::bind(func, base, std::placeholders::_1);
はこれを行うには良い方法、またはこの作業を取得するために、おそらく方法はありますか?
私が気づいたことは興味深いものです。 std::shared_ptr
を使用した場合、use_count()
は元のコードでstd::bind
への呼び出しで増分されます。したがって、私は自分のマネージャーのメンバーを解除しない限り、オブジェクトを手動でリセット/破棄することはできません。この動作が文書化されているところでは、私は通常cppreferenceを使用しますか?
:How can I use polymorphism with std::function?
ながらリストを変更するときに警告読者は、スレッドの問題を認識しておく必要があり、http://en.cppreference.com/w/cpp/utility/functional/bindは「言いますstd :: bindの戻り値の型は、std :: forwardから構築されたargs ...、[...]のそれぞれに対して1つのオブジェクトを保持します(...(arg_i))。同じページの下に "バインドする引数はコピーまたは移動されます"。あなたがshared_ptr lvalueを渡したので、あなたはコピーを持っています。 –
Cubbi
'&MyClass :: myDouble'は、とにかく' std :: function 'に変換されません。 –
@ T.C私はこれを十分に認識しているので、その理由がわかります。私はそのシグネチャがどんなものか気にしません、 'db.setFunction(myClass、MyClass :: myDouble);のような呼び出しをしたいです。 –