boost::signals2: 连接到不同 class 的插槽
boost::signals2: connect to a slot of a diffeent class
我正在尝试在我的程序中使用 boost::signals2 功能。
在我的名为“Solid”的“Main Class”中,我有一个成员在构造函数体内初始化(因此 在 成员初始化列表之后),如下所示:
pointer_M = boost::make_shared<OtherClass>(/*parameters,...*/);
如果信号由某个函数触发,我不想调用“OtherClass”的成员(pointer_M 指向),而是调用“Solid”的成员,即class 刚刚初始化 pointer_M。
我尝试了以下方法:
boost::signals2::connection tria_signal = /*...*/.connect( boost::signals2::signal<void()>::slot_type(&Solid::call_this_function, pointer_M.get()).track(pointer_M) );
"call_this_function" 是 Solid 的成员函数。不幸的是有一堆错误信息。 “OtherClass”和“Solid”没有继承关系。
由于我对 boost 非常缺乏经验,因此我希望能得到一些如何解决我的问题的建议。
最佳
But is that what I am trying to achieve possible at all?
关键是,如果没有更清晰的描述,我们就无法分辨。这听起来很简单:信号专门用于解耦呼叫者和被呼叫者。
所以让我为您补充 。我将回避您在该行中显示的巨大的类型过度复杂化:
boost::signals2::connection tria_signal =
/*...*/.connect(boost::signals2::signal<void()>::slot_type(
&Solid::call_this_function, pointer_M.get())
.track(pointer_M));
插槽的整体思想是它们使用类型擦除来泛化可调用对象。只需以任何兼容形式提供您的可调用对象,让库推断出神秘的实现类型。
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
auto tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.pointer_M->test();
}
版画
Solid was here
Crystal Ball:我们能猜出问题所在吗?
也许我们可以猜到问题所在:看起来您正在努力跟踪 pointer_M
指向的对象的生命周期。这没有用,因为 OtherClass
首先拥有信号,这意味着当 OtherClass
消失时所有连接都会断开。
正确的生命周期管理
您可能希望在 Solid
对象的生命周期结束时断开连接,而不是 OtherClass
。一般来说,我建议在这里使用 scoped_connection
:
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
boost::shared_ptr<OtherClass> keep;
{
Solid s;
std::cout << "Testing once:" << std::endl;
s.pointer_M->test();
keep = s.pointer_M; // keep the OtherClass alive
} // destructs Solid s
std::cout << "Testing again:" << std::endl;
keep->test(); // no longer connected, due to scoped_connection
}
版画
Testing once:
Solid was here
Testing again:
简化
在你的例子中,OtherClass
已经被 Solid
拥有(至少它是创建的)。似乎在这里根本不需要共享指针:
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
Solid() : oc_M(1,2,3) {
tria_signal = oc_M.tria.connect(
boost::bind(&Solid::call_this_function, this));
}
void test() { oc_M.test(); }
private:
OtherClass oc_M;
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.test();
}
因为成员是按照声明的相反顺序销毁的,所以这是完全安全的。
建筑宇航
如果您知道自己在做什么,并且 pointer_M
实际上需要共享,那么您可能想要跟踪 that 指针。您可能应该考虑将 Solid
也设为 enable_shared_from_this
。如果您想成为真正的“Enterprise Grade Engineer™”,您或许可以使用别名构造函数做一些花哨的事情:What is shared_ptr's aliasing constructor for?
我正在尝试在我的程序中使用 boost::signals2 功能。 在我的名为“Solid”的“Main Class”中,我有一个成员在构造函数体内初始化(因此 在 成员初始化列表之后),如下所示:
pointer_M = boost::make_shared<OtherClass>(/*parameters,...*/);
如果信号由某个函数触发,我不想调用“OtherClass”的成员(pointer_M 指向),而是调用“Solid”的成员,即class 刚刚初始化 pointer_M。
我尝试了以下方法:
boost::signals2::connection tria_signal = /*...*/.connect( boost::signals2::signal<void()>::slot_type(&Solid::call_this_function, pointer_M.get()).track(pointer_M) );
"call_this_function" 是 Solid 的成员函数。不幸的是有一堆错误信息。 “OtherClass”和“Solid”没有继承关系。
由于我对 boost 非常缺乏经验,因此我希望能得到一些如何解决我的问题的建议。
最佳
But is that what I am trying to achieve possible at all?
关键是,如果没有更清晰的描述,我们就无法分辨。这听起来很简单:信号专门用于解耦呼叫者和被呼叫者。
所以让我为您补充
boost::signals2::connection tria_signal =
/*...*/.connect(boost::signals2::signal<void()>::slot_type(
&Solid::call_this_function, pointer_M.get())
.track(pointer_M));
插槽的整体思想是它们使用类型擦除来泛化可调用对象。只需以任何兼容形式提供您的可调用对象,让库推断出神秘的实现类型。
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
auto tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.pointer_M->test();
}
版画
Solid was here
Crystal Ball:我们能猜出问题所在吗?
也许我们可以猜到问题所在:看起来您正在努力跟踪 pointer_M
指向的对象的生命周期。这没有用,因为 OtherClass
首先拥有信号,这意味着当 OtherClass
消失时所有连接都会断开。
正确的生命周期管理
您可能希望在 Solid
对象的生命周期结束时断开连接,而不是 OtherClass
。一般来说,我建议在这里使用 scoped_connection
:
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
boost::shared_ptr<OtherClass> keep;
{
Solid s;
std::cout << "Testing once:" << std::endl;
s.pointer_M->test();
keep = s.pointer_M; // keep the OtherClass alive
} // destructs Solid s
std::cout << "Testing again:" << std::endl;
keep->test(); // no longer connected, due to scoped_connection
}
版画
Testing once:
Solid was here
Testing again:
简化
在你的例子中,OtherClass
已经被 Solid
拥有(至少它是创建的)。似乎在这里根本不需要共享指针:
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
Solid() : oc_M(1,2,3) {
tria_signal = oc_M.tria.connect(
boost::bind(&Solid::call_this_function, this));
}
void test() { oc_M.test(); }
private:
OtherClass oc_M;
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.test();
}
因为成员是按照声明的相反顺序销毁的,所以这是完全安全的。
建筑宇航
如果您知道自己在做什么,并且 pointer_M
实际上需要共享,那么您可能想要跟踪 that 指针。您可能应该考虑将 Solid
也设为 enable_shared_from_this
。如果您想成为真正的“Enterprise Grade Engineer™”,您或许可以使用别名构造函数做一些花哨的事情:What is shared_ptr's aliasing constructor for?