以下のコード (問題の実例として実装) に見られるように、内部クラスから外部クラスに中継される中間クラスにシグナルを送信しようとしています。
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <iostream>
class inner {
public:
template <class T>
void register_callback(boost::function<void(T *)> cb, T *obj)
{
sig_inner_.connect(boost::bind(cb, boost::ref(obj)));
}
void trigger()
{
std::cout << "inner" << std::endl;
sig_inner_();
}
private:
boost::signals2::signal<void()> sig_inner_;
};
class mid {
public:
mid() { inner_obj.register_callback<mid>(&mid::handle_sig_mid, this); }
template <class T>
void register_callback(boost::function<void(T *)> cb, T *obj)
{
sig_mid_.connect(boost::bind(cb, boost::ref(obj)));
}
void trigger() { sig_mid_(); }
void inner_trigger() { inner_obj.trigger(); }
void handle_sig_mid()
{
std::cout << "mid" << std::endl;
trigger();
}
private:
boost::signals2::signal<void()> sig_mid_;
inner inner_obj;
};
class outer {
public:
outer() { mid_obj.register_callback<outer>(&outer::handle_sig_outer, this); }
void inner_trigger() { mid_obj.inner_trigger(); }
private:
mid mid_obj;
void handle_sig_outer() { std::cout << "outer" << std::endl; }
};
int main()
{
outer outer_obj;
outer_obj.inner_trigger();
return 0;
}
望ましい結果の代わりに:
inner
mid
outer
プログラムを実行すると、実際には次のようになります。
inner
mid
mid
続いてクラッシュ。
「this」のアドレスが通常のメソッドで期待するものとハンドラーで異なることに既に気付きましたが、それを回避する方法がわかりません。
これに対して私が見つけた唯一の解決策は、外部クラスのシグナルをそのハンドラーに接続し、ポインター(この場合はunique_ptr)を内部クラスに格納することでした。これにより、中継する必要がなくなりましたが、感じません信号を使用する安全な方法のように。
私はC ++、特にブーストが初めてなので、内部クラスから外部クラスのコールバックをクリーンで安全な方法でトリガーする方法がよくわかりません。