После прочтения статьи «Простейший делегат на C++», я понял лишь то, что не понял я абсолютно ничего – наглухо. Может это потому что автор апеллировал в своих мыслях к понятию делегатов в языке C#, который я знаю чуть менее чем никак. Зато я знаю objective C, в котором, делигерование встречается достаточно часто и подход к делигированию там вполне не плохо переностся на C++, а раз у людей на нем пишущих есть потребность в делегатах, то может такой подход им понравится больше. Сразу оговорка – так как в objective C связывание объекта с методом происходит полностью runtime, зделать все так же на плюсах не выйдет, но тут великий Страуструп оставил нам крохотную щель — таблицу виртуальных функций, вот через нее и просочимся.
Для начала потребно разъяснить каков подход к делегированию в objective C.
Итак, по правилам хорошего тона у нас должен быть интерфейс (@interface – некий аналог класса в плюсах, далее назовем его тоже классом), и протокол с объявлением методов-делегатов (@protocol), класс которому нужно установить делегаты должен иметь наследование от этого протокола (говоря языком «кокошников» поддерживать протокол), а класс который вызывает делегаты иметь указатель на класс с методами делегатами и реализованной поддержкой протокола (правда, из-за динамического связывания наследование вовсе не обязательно – просто копипастим имена методов протокола нужному классу, определяем что им делать – компилятор покажет warning, но все работает, а вот на C++ такое неполучится, тут нужно все выше писанное соблюдать р��вностно).
Теперь переходим к коду. Для начала объявим пару аналогичную протокол/интерфейс но с поправкой на то что у нас C++;
Для наглядности в _interface только имена функций, их алгоритмы обьявятся отдельным файлом, а пока стоит обсудить тот код что выше. Структура _protocol есть наш список методов делегатов, мужно наследовать от нее, а далее делегирующий некие действия интерфейс (назван _interface), люди знающие objective C уже обратили внимание что указатель на класс-делегат имеет определенный тип. Компелятор должен установить связь через таблицу виртуальных функций, а для этого указатель должен иметь тип обьекта с такой таблицей.
Класс _interface включает следуюющие атрибуты: указатель на строку, число целое, число дробное – достаточно чтобы наглядно продемонстрировать как делегат повлияет на эти приватные параметры. А теперь стоит показать что делает наш интерфейс:
Обратить внимание (!):
А теперь самое время предьявить листинг где делигирующий и делегат взаемодействуюют:
Консоль с резельтатами:

Вот и все по коду – строка развернута задом на перед, целочисленный атрибут изменен частично по правилам обьекта делигирующего, частично по усмотрению обьекта делигата, вполне хорошо демонстрирует суть делигирования.
Понятно что этот подход не идеален, но C++ вообще не предрасполагает к делегированию, без костылей никак, обьект которому делегируют возможно должен иметь наследование от другог обьекта и добавлять к наследованию протокол может не всегда получится (запрет на примение множественного наследования в проекте, виртуальные функции в других классах родителях). Хотя зачем нам голова? Правильно – придумывать решения, если с наследованием никак — стандарт С++ вполне позволяет писать такое:
Внешний и внутренний класс можно так крепко сцепить, что их взаимодействие даст все что нам необходимо.
РЕЗЮМЕ:
1) Нужно создать для класса который должен делегировать, класс-протокол с виртуальными функцими делегатами и работать с обьектом делегируемым через указатель.
2) Делегируемый класс должен быть унаследован от протокола.
Для начала потребно разъяснить каков подход к делегированию в objective C.
Итак, по правилам хорошего тона у нас должен быть интерфейс (@interface – некий аналог класса в плюсах, далее назовем его тоже классом), и протокол с объявлением методов-делегатов (@protocol), класс которому нужно установить делегаты должен иметь наследование от этого протокола (говоря языком «кокошников» поддерживать протокол), а класс который вызывает делегаты иметь указатель на класс с методами делегатами и реализованной поддержкой протокола (правда, из-за динамического связывания наследование вовсе не обязательно – просто копипастим имена методов протокола нужному классу, определяем что им делать – компилятор покажет warning, но все работает, а вот на C++ такое неполучится, тут нужно все выше писанное соблюдать р��вностно).
Теперь переходим к коду. Для начала объявим пару аналогичную протокол/интерфейс но с поправкой на то что у нас C++;
//файл SomeInterfaceAndProtocol.hpp #ifndef demo_interface_protocol #define demo_interface_protocol struct _protocol //аналог протокола для objC, сам по себе он не юзабилен, но далее используя наследование можно создавать делегаты { void virtual ActionString(char *)=0;//методы делегаты; int virtual ActionRetNums(double S)=0; int virtual length(char *)=0; }; class _interface //класс который делигирует { private: char *text; double flo; int lo; _protocol *delegate;// собственно главный герой повествования public: _interface(int Z, double f, char *u); _interface(int Z, double f, char *u, _protocol *_); void SetDelegate(_protocol *_); void action(); void viewResults(); ~_interface(); }; #endif
Для наглядности в _interface только имена функций, их алгоритмы обьявятся отдельным файлом, а пока стоит обсудить тот код что выше. Структура _protocol есть наш список методов делегатов, мужно наследовать от нее, а далее делегирующий некие действия интерфейс (назван _interface), люди знающие objective C уже обратили внимание что указатель на класс-делегат имеет определенный тип. Компелятор должен установить связь через таблицу виртуальных функций, а для этого указатель должен иметь тип обьекта с такой таблицей.
Класс _interface включает следуюющие атрибуты: указатель на строку, число целое, число дробное – достаточно чтобы наглядно продемонстрировать как делегат повлияет на эти приватные параметры. А теперь стоит показать что делает наш интерфейс:
#include "SomeInterfaceAndProtocol.hpp" #include "math.h" class realprotocol: public _protocol//вот класс, которому мы будем делегировать полномочия { int length(char *text) //пусть просто подщитает длинну строки { int i=0; while(text[i])i++; return i; } void ActionString(char *stroka)//пусть этот пример разворачивает строку задом на перед { int len=this->length(stroka); int k=0; char Z; while(k!=(int)(len/2)) { Z=stroka[k]; stroka[k]=stroka[len-1-k]; stroka[len-1-k]=Z; k++; }; } int ActionRetNums(double S)//пусть возвращает целую часть корня { return (int)sqrt(S); } };
Обратить внимание (!):
class realprotocol: public _protocol – писать надо так, если класс обьявить просто class realprotocol, а дальше написать все также – это работать не будет, более того без развратного типоблудия компелятор это даже не соберет, objective C в этом плане более сговорчив (см. выше), но тут есмь свои недостатки (и много).А теперь самое время предьявить листинг где делигирующий и делегат взаемодействуюют:
#include <cstdlib> #include "SomeInterfaceAndProtocol.hpp" #include "realprotocol.hpp" realprotocol delegat; _interface delegator=_interface(44, 66.888, "seidal eht rof maj"); int main(int argc, char *argv[]) { delegator.SetDelegate(&delegat); delegator.action(); delegator.viewResults(); system("PAUSE"); return EXIT_SUCCESS; }
Консоль с резельтатами:

Вот и все по коду – строка развернута задом на перед, целочисленный атрибут изменен частично по правилам обьекта делигирующего, частично по усмотрению обьекта делигата, вполне хорошо демонстрирует суть делигирования.
Понятно что этот подход не идеален, но C++ вообще не предрасполагает к делегированию, без костылей никак, обьект которому делегируют возможно должен иметь наследование от другог обьекта и добавлять к наследованию протокол может не всегда получится (запрет на примение множественного наследования в проекте, виртуальные функции в других классах родителях). Хотя зачем нам голова? Правильно – придумывать решения, если с наследованием никак — стандарт С++ вполне позволяет писать такое:
class externalclass:someclass1, someclass2 { private: class internalclass:public _protocol { //бла-бла-бла }; internalclass forDelegate; public: _protocol* GetForDelegate() { return &forDelegate; } };
Внешний и внутренний класс можно так крепко сцепить, что их взаимодействие даст все что нам необходимо.
РЕЗЮМЕ:
1) Нужно создать для класса который должен делегировать, класс-протокол с виртуальными функцими делегатами и работать с обьектом делегируемым через указатель.
2) Делегируемый класс должен быть унаследован от протокола.
