c++ - boost::signals2: 连接到不同类的插槽
问题描述
我正在尝试在我的程序中使用 boost::signals2 功能。在我的名为“Solid”的“主类”中,我有一个在构造函数体内初始化的成员(所以在成员初始化器列表之后),如下所示:
pointer_M = boost::make_shared<OtherClass>(/*parameters,...*/);
如果信号是由某个函数触发的,我不想调用“OtherClass”的成员(pointer_M 指向的),而是“Solid”的成员,即刚刚初始化 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 非常缺乏经验。
最好的
解决方案
但这就是我想要实现的目标吗?
关键是如果没有更清晰的描述,我们就无法判断。这听起来很简单:信号专门用于解耦调用者和被调用者。
所以让我为你编造你的“虚拟代码”。我将回避您在该行中显示的巨大的类型过度复杂性:
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
水晶球:我们能猜出问题吗?
也许我们可以猜到问题所在:看起来您正在努力跟踪 所指向的对象的生命周期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:
简化
在您的情况下, theOtherClass
已经由 the 拥有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
实际上需要共享,那么您可能想要跟踪该指针。Solid
您可能也应该考虑制作enable_shared_from_this
. 如果您想成为真正的“企业级工程师™”,您也许可以对别名构造函数做一些花哨的事情:shared_ptr 的别名构造函数是干什么用的?
推荐阅读
- c# - 如何打破绑定以便删除资产
- oauth-2.0 - 通过 OAUTH 2 获取令牌时查看 Postman 中的一系列请求
- c# - asp.net 核心在视图中显示表格,每行旁边都有按钮。单击按钮后对数据库进行更改
- security - Travis CI 中的文件加密如何工作?
- powershell - Powershell获取给定路径内的扩展文件
- javascript - 反应打印运动属性内的值
- azure - 如何使用 AzureCLI 执行 powershell 脚本?
- wordpress - WordPress 灯箱库:将文字链接打开到图片库
- excel - 将行切片在一起
- mysql - 非法混合排序规则 (utf8mb4_unicode_ci,COERCIBLE) 和 (utf8mb4_general_ci,COERCIBLE) 用于“like”操作