Ответ 1
Это совершенно правильный подход к хранению обработчиков событий.
Однако я хотел бы указать некоторые подробности относительно подписи вашей функции для добавления обратного вызова. Вы беспокоитесь о передаче его по значению, а не по ссылке. В вашем примере у вас есть:
void On(EventType OnEventType,std::function<void()>&& Callback)
Это хорошо, если вы будете связывать это только с rvalues. Однако, если нет особых причин, по которым вы хотите запретить это, я бы рекомендовал, чтобы у вас всегда был метод, который принимает параметры по значению или ссылочной ссылке lvalue и добавляет ссылочную версию rvalue в качестве дополнения, если это будет сочтено необходимым.
Не имея метода, который принимает ссылку на lvalue, ваш код в настоящее время не будет скомпилирован, учитывая это:
std::function<void()> func([](){/*something clever*/});
// Do something necessary with func, perhaps logging or debug prints.
Button->On(EventType::Click, func);
Для простоты, когда вы выбираете способ передачи значения, вы можете просто следовать этим рекомендациям в целом:
- Если вам нужна копия или намеревается изменить отправленное значение, не требуя изменения фактического переданного объекта: перейдите по значению.
- Если вы намерены изменить отправленное значение и хотите, чтобы эти изменения влияли на переданный фактический объект: pass by reference.
- Если вы не хотите изменять переданный объект, но считайте полезным избегать копирования: pass by const reference.
- Если вы берете параметры по значению, ссылке или const-ссылке и считаете, что есть ценные оптимизации, которые могут быть достигнуты с использованием знания о том, что входной параметр является временным: также разрешить передачу по ссылке rvalue.