#c #boost
Вопрос:
В моем частном проекте я использую boost::signals2 для отправки сообщений из нескольких классов общему получателю. Мой вопрос: как я могу отправлять сообщения из конструктора класса? Проблема в том, что сигнал в этом случае не существует до тех пор, пока не будет создан экземпляр объекта класса A (до тех пор, пока не будет выполнен конструктор). Но на данный момент еще не было возможности для какого-либо другого кода установить слот.
Я попытался использовать статический импульс::сигнал2::сигнал<void(const std::строка и Msg)>, но затем я получаю ошибки загрузчика «неопределенная ссылка на класс::сигнал».
Ниже приведена очень урезанная версия моего кода для иллюстрации. Вопрос в следующем: как класс B может получить сообщение от конструктора класса A? Или другими словами: как я могу подключить слот к сигналу класса A до выполнения конструктора класса A?
class A {
public:
/*static*/ boost::signals2::signal<void(const std::string amp; Msg)> sigA;
A() { sigA("message from constructor A"); }
};
class B {
B() {
A a;
a.sigA.connect([](const std::string amp; msg) { std::cerr << msg << 'n'; } );
}
};
Для вашей информации: я использую fedora 33, gcc 11.2.1 и C 17.
Пожалуйста, извините мой английский: это не мой родной язык, и мне не хватает некоторого опыта…
Ответ №1:
Технически, вы могли бы передать слот class A
конструктору.
class A {
public:
A(boost::signals2::slot<void(const std::string amp;)> slot) {
sigA.connect(slot);
sigA("message from constructor A"); }
};
class B {
B() {
A a([](const std::string amp; msg) { std::cerr << msg << 'n'; });
}
};
Обратите внимание, что семантика немного странная. На этот раз нет никакого способа получить connection
объект. вы могли бы использовать параметр out в конструкторе, но это действительно запах кода.
Как правило, конструкторы используются для инициализации объекта, а не для выполнения логики, которая может повлиять на объекты, не являющиеся членами класса.
Я бы настоятельно рекомендовал подписаться на слот отдельным способом.
Комментарии:
1. Я на 100% согласен с вашими ответами. Я думаю, что я значительно упростил свой пример кода. Таким образом, исходная проблема, которую я описал в своем вопросе, может быть покрыта плохо выбранным примером. Тем временем я сам нашел решение (см. Ниже). Спасибо вам за ваш ответ
Ответ №2:
Тем временем я сам нашел решение своей проблемы. Ниже приведен полностью рабочий пример того, как конструктор класса A запускает сигнал, который сам является (статическим) членом класса A:
#include <string>
#include <iostream>
#include <functional>
#include <boost/signals2/signal.hpp>
class A {
public:
using Signal = boost::signals2::signal<void(const std::string amp; Msg)>;
static Signal sigA;
A() { sigA("message from constructor A"); }
};
A::Signal A::sigA;
class B {
public:
B() {}
void disp(const std::string amp; msg) { std::cout << msg << 'n'; }
};
int main()
{
B b; // slot b.disp() now exists
auto slot = std::bind(amp;B::disp, b, std::placeholders::_1);
A::sigA.connect(slot); // subscribe slot b.disp() to A::sigA
A a; // constructor of class A fires signal sigA, b.disp() writes to cout
};