如何提前绑定boost::signals2信号槽以接收类构造函数发出的消息
问题原因
- 静态信号链接错误:类内声明的非inline静态成员变量仅为声明,缺少定义导致链接时出现
undefined reference报错。 - 构造函数信号接收失败:现有代码先实例化A执行构造函数发信号,后绑定槽,信号发送时没有已连接的槽,自然无法接收。
解决方案
方案1:使用静态信号(适合所有A实例共用同一信号的场景)
静态信号属于类本身,不属于实例,不需要创建A的实例就可以提前绑定槽。C++17标准支持inline static类内直接定义静态成员,无需额外类外声明,先绑定槽再实例化A即可接收构造函数发出的信号:
#include <boost/signals2.hpp> #include <iostream> #include <string> #include <utility> class A { public: // C++17 inline static 类内直接定义静态信号 inline static boost::signals2::signal<void(const std::string & Msg)> sigA; A() { sigA("message from constructor A"); } }; class B { public: B() { // 先绑定槽,再实例化A A::sigA.connect([](const std::string & msg) { std::cerr << msg << '\n'; }); // 绑定完成后创建A实例,构造函数的信号会被正常接收 A a; } }; int main() { B b; return 0; }
方案2:构造注入槽函数(适合每个A实例需独立信号的场景)
不需要全局静态变量,构造A实例时直接传入槽函数,绑定完成后再发信号,耦合更低:
#include <boost/signals2.hpp> #include <iostream> #include <string> #include <utility> class A { public: boost::signals2::signal<void(const std::string & Msg)> sigA; // 模板接收任意可调用对象作为槽,先绑定再发信号 template<typename Slot> explicit A(Slot&& slot) { sigA.connect(std::forward<Slot>(slot)); sigA("message from constructor A"); } }; class B { public: B() { // 实例化A时直接传入槽函数 A a([](const std::string & msg) { std::cerr << msg << '\n'; }); } }; int main() { B b; return 0; }
兼容C++17之前版本的静态信号写法
如果需要兼容旧C++标准,去掉类内的inline关键字,在类外全局作用域补充静态成员的定义即可:
// 类A内的声明 class A { public: static boost::signals2::signal<void(const std::string & Msg)> sigA; A() { sigA("message from constructor A"); } }; // 类外全局作用域补充定义 boost::signals2::signal<void(const std::string & Msg)> A::sigA;
内容的提问来源于stack exchange,提问作者OldRalle
相关产品推荐
相关产品推荐

