Публичный объект boost::signal

Я публикую свои boost::signal, потому что мне лень.

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

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

... вместо инкапсуляции с помощью Button::OnClicked(boost::function<void()>).

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


person Community    schedule 14.02.2009    source источник


Ответы (4)


Это зависит.

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

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

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

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

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

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

SIGNAL(void(),clicked)

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

ИЗМЕНИТЬ

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

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

person Community    schedule 14.02.2009
comment
спасибо; Можете ли вы рассказать мне о конкретном случае, когда вам это нужно? - person ; 14.02.2009

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

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

Решение для нас состоит в следующем:

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

Хоть что-то учитывать!

person timpatt    schedule 12.01.2012

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

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

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

person MattyT    schedule 15.02.2009

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

person StackedCrooked    schedule 19.09.2009