class Base { typedef void (Base::*delegate)(SomeClass1 * obj1, SomeClass2 * obj2); //сигнатура делегата QHash<QString,delegate> fdelegateHash;protected: void registerDelegate(const QString & delegateId, delegate delegatePtr);public:void executeDelegate(const QString & delegateName, SomeClass1 * obj, SomeClass2 * obj2);};
#include <iostream>#include <functional>using namespace std;//предположим у нас есть GUI библиотека //при помощи которой мы можем создавать кнопки//однако такие библиотечные классы ничего не знают о классах целевого бизнес-приложенияstruct Button{ typedef std::function<void()> EventClick; EventClick mEventClick; //имитируем "клик" на кнопке. void SimulationClick()const { cout<<"GUI: Click!\n"; //когда кнопка впадает в состояние "меня кликнули", //она должна испустить сигнал - предупредить о факте клика заинтересованные объекты бизнес-приложения. //делегат позволяет зделать это, без необходимости знать о точных типах получателей события if(mEventClick) mEventClick(); } };//а этот класс - часть бизнес-модели приложения//модель никак не связанна с GUI, и ничего не знает о её классах//ровно, как и GUI ничего не знает о моделиstruct Model{ //модель реализует поведение на нажатие кнопки. //точный тип кнопки при этом не имеет значение. //природа источника события не имеет значения. void OnClick()const { cout<<"Model:button was click\n"; }};//бизнес-приложениеint main(){ std::cout << "Hello, world!\n"; //здесь мы создаем GUI, и модель. //И устанавливаем между ними связь. //Обратите внимание: //изначально, ни модель ни GUI не подозревают о существовании друг друга. //Для организации взаимодействия между ними используется технология делегатов. Button button; Model model; //заряжаем делегат. button.mEventClick = [&model](){ model.OnClick(); }; //теперь, когда на кнопку нажмут, она дернет делегат, который дернет лямбду, которая дернет модель. // есть и другие способы передачи сигнала. Например: button.mEventClick = std::bind(&Model::OnClick, &model); //используя шаблонную магию, бинд генерирует функтор, по своему действию аналогичный лямбде. //суть проста: std::function это просто тонкая обертка над функторами, //которые дергают функции или функции-члены получателей сообщения //теперь имитирует нажатие на кнопку: button.SimulationClick();}
//заряжаем делегат. button.mEventClick = [&model](){ model.OnClick(); }; //теперь, когда на кнопку нажмут, она дернет делегат, который дернет лямбду, которая дернет модель. // есть и другие способы передачи сигнала. Например: button.mEventClick = std::bind(&Model::OnClick, &model);}
#include <iostream>#include <functional>using namespace std;struct CustomFunctor{ bool operator()(int v)const { return v%2 == 0; }};int main(){ std::cout << "Hello, world!\n"; //умеет запускать любые функции/функции-члены //которые возвращают тип bool //и принимают тип int typedef std::function<bool(int)> Executer; //инициализируем делегат кастомным функтором //ПРИМЕЧАНИЕ: operator() функтора //должен соотвествовать типу функции bool(int) //проверка типов выполняется времени компиляции Executer ex = CustomFunctor(); //теперь можно запускать const bool result1 = ex(10); const bool result2 = ex(11); if(result1) cout<<"ex(10) is true\n"; else cout<<"ex(10) is false\n"; if(result2) cout<<"ex(11) is true\n"; else cout<<"ex(11) is false\n";}