Ответ 1
Предпочитают хорошо определенные интерфейсы над обратными вызовами
Проблема с std::function
(ранее boost::function
) заключается в том, что большую часть времени вам нужно иметь обратный вызов методу класса и, следовательно, необходимо привязать this
к объекту функции. Однако в вызывающем коде вы не можете узнать, существует ли еще this
. На самом деле, вы даже не подозреваете, что даже существует this
, потому что bind сформировал подпись вызывающей функции в том, что требует вызывающий.
Это может привести к возникновению странных сбоев, поскольку обратный вызов пытается запустить методы для классов, которые больше не существуют.
Вы можете, конечно, использовать shared_from_this
и привязать shared_ptr к обратному вызову, но тогда ваш экземпляр никогда не исчезнет. Человек, у которого есть обратный вызов, теперь участвует в вашей собственности, даже если они даже не знают об этом. Вероятно, вам нужно больше предсказуемого владения и разрушения.
Другая проблема, даже если вы можете заставить callback работать нормально, с обратными вызовами, код может быть слишком развязан. Отношения между объектами могут быть настолько трудными для выяснения, что читаемость кода уменьшается. Однако интерфейсы обеспечивают хороший компромисс между соответствующим уровнем развязки с четко определенной взаимосвязью, как это определено в контракте интерфейса. Вы также можете более четко указать в этой связи проблемы, например, кто владеет кем, порядок уничтожения и т.д.
Дополнительная проблема с std::function
заключается в том, что многие отладчики не поддерживают их хорошо. В VS2008 и повышающих функциях вам нужно пройти около 7 уровней, чтобы перейти к вашей функции. Даже если все остальные вещи равны обратному результату, лучший выбор, явное раздражение и время, потраченное впустую, случайно перешагнув цель std::function
, являются достаточной причиной, чтобы избежать этого. Наследование является основной особенностью языка, и переход к переопределенному методу интерфейса является мгновенным.
Наконец, я просто добавлю , у нас нет делегатов в С++. Делегаты в С# являются основной частью языка, так же как наследование - на С++ и С#. У нас есть функция std library, IMO - один слой, удаленный из функциональности основного языка. Таким образом, он не будет столь тесно интегрирован с другими основными функциями языка. Вместо этого он помогает формализовать идею объектных объектов, которые были идиомой С++ в настоящее время.