Public boost::signal object

Я делаю мой boost::signalПубличный, потому что я ленивый.

class Button {
public:
    signal<void()> clicked;
};

int main() {
    Button btn;
    btn.clicked.connect(handleClick);
}

... а не заключать в капсулу с Button::OnClicked(boost::function<void()>),

Это собирается вернуться и укусить меня?

4 ответа

Решение

Это зависит.

Это укусило меня раньше, когда я хотел добавить какую-то особую логику каждый раз, когда объект подключался к сигналам другого объекта. Это наиболее вероятный случай, чтобы укусить вас.

Кроме того, это может затруднить точное отслеживание того, когда другие объекты подключаются к какому-либо данному объекту.

Я бы сказал, скрыть соединения за функцией, чтобы быть на безопасной стороне.

Я обычно использую макрос для определения ванильной функции.

#define SIGNAL(slot,name) connection name(function<slot> func) { return _##name##.connect(func);}

И тогда в определении класса:

SIGNAL(void(),clicked)

Это предполагает, что вы следуете соглашению о присвоении имени сигналу _clicked, но вы можете заменить любое соглашение. Обычно он поддерживает чистоту интерфейса для всех ваших классов. Когда вы хотите добавить специальную логику соединения, вы можете, не изменяя все другие объекты, которые используют сигнал.

РЕДАКТИРОВАТЬ

Один случай был, когда объект сигнала был фактически перемещен в реализацию делегата внутри другого класса, но для объектов все еще имел смысл соединяться через исходный класс. Это сломало все места, которые пытались подключиться к нему. Если бы они использовали средства доступа к функциям для подключения, это было бы так же просто, как изменить функцию для поиска сигнала в делегате. Но как это было сломано все пользователи оригинального класса.

Или, когда я хотел каждый раз регистрировать что-то, связанное с определенным сигналом. Это было сделано только для целей отладки, но может быть очень полезно, если вы подозреваете, что происходит что-то нехорошее, например циклы в ваших сигнальных соединениях.

Я наткнулся на вескую причину не делать этого.

Мы смотрим на использование сторонней библиотеки, которая выставляет boost:: сигналы на внешнем интерфейсе. Эта библиотека зависит от версии boost с набором определений компилятора, которые двоично несовместимы со стандартными определениями компилятора Visual Studio, которые мы используем в нашем проекте. Всякий раз, когда мы пытаемся вызвать signal.connect сторонней библиотеки, вещи умирают.

Решением для нас является либо:

  1. Перекомпилируйте все наши исходные и зависимые библиотеки с предоставленной ими улучшенной версией.
  2. Оберните сигналы повышения и скройте реализацию

Что-то рассмотреть, по крайней мере!

Я также установил их как общедоступные и использую в качестве имени объекта верхний верблюжий регистр. Этот подход никогда не имел неприятных последствий для меня.

Ну, этот вопрос действительно не имеет ничего общего с boost::signal или же function - это все о капсулировании.

У клиента из Button классу нужен полный доступ к clicked? Если все, что они могут сделать, это подписаться на него, то разрешите только это с OnClicked метод. Разоблачение больше, чем это , вероятно, укусит вас ИМХО.

Как всегда, вы балансируете затраты и выгоды. В этом случае стоимость очень низкая. Если бы вы были в моей команде, я настоятельно рекомендую вам добавить OnClicked метод.

Другие вопросы по тегам