Делегаты для C++
От: о_О
Дата: 04.02.11 20:28
Оценка: 19 (1)
Здравствуйте

Выкладываю реализации делегатов TSingleDelegate и TMultiDelegate, которые использую сам. Возможно кому-то пригодится, кто любит простоту, удобство и эффективность. Код базируется на делегатах от Don Clugston, по этому, кто уже их использовал, осваивать не придется (только для VC++)

Ссылка на архив

Пример/туториал:
  Скрытый текст
#include <vector>
#include <delegate.hpp>

///////////////////////////////////////////////////////////////////////////////

void sf3(int, int, int) { std::cout << __FUNCTION__ << "()" << std::endl; }

class A
{
public:
    void mf3(int,int,int) { std::cout << __FUNCTION__ << "()" << std::endl; }
    void cf3(int,int,int) const { std::cout << __FUNCTION__ << "() const" << std::endl; }
    static void sf3(int,int,int) { std::cout << __FUNCTION__ << "()" << std::endl; }
    virtual void vf3(int,int,int) { std::cout << __FUNCTION__ << "() virtual" << std::endl; }
    virtual void vcf3(int,int,int) const { std::cout << __FUNCTION__ << "() virtual const" << std::endl; }
};

class B : public A
{
private:
    WCHAR _buf[256];

public:
    virtual void vf3(int,int,int) { std::cout << __FUNCTION__ << "() override" << std::endl; }
    virtual void vcf3(int,int,int) const { std::cout << __FUNCTION__ << "() override const" << std::endl; }
};

///////////////////////////////////////////////////////////////////////////////

void wmain(int argc, wchar_t** args)
{
    typedef TSingleDelegate<void(int,int,int)> TSD3;
    typedef TMultiDelegate<void(int,int,int)> TMD3;
    std::vector<TSD3> sdl;
    std::vector<TMD3> mdl;

    A a;
    B b;
    const A* ac = new A();
    const B* bc = new B();

    /* TSingleDelegate - содержит единственную связь */

    /* конструкторы */
    TSD3 sd01;                            //пустой делегат, при вызове проверяется на NULL,- безопасно
    TSD3 sd02(sf3);                    //статическая функция
    TSD3 sd03 = sf3;                //статическая функция (вид сбоку)
    TSD3 sd04(&A::sf3);            //статическая функция класса
    TSD3 sd05 = &A::sf3;        //статическая функция класса (вид сбоку)
    TSD3 sd06 = &B::sf3;        //всё та же встатическая функция
    TSD3 sd07(&a, &A::mf3);    //фукнция класса
    TSD3 sd08(&a, &A::cf3); //константная функция класса
    TSD3 sd09(ac, &A::vf3); //виртуальная функция константного класса
    TSD3 sd10(&b, &B::mf3); //функция другого класса
    TSD3 sd11(bc, &B::cf3); //константная функция другого константного класса
    TSD3 sd12(bc, &B::vcf3);//перегруженная виртуальная константная функция другого константного класса
    TSD3 sd13(sd10);                //копирование из другого делегата
    TSD3 sd14 = sd12;                //копирование из другого делегата (вид сбоку)
    TSD3 sd15(sd11.GetMemFunc());    //копирование из анонимного указателя (TMemFunc)
    sd15.Clear(), sd15.Unbind();    //удаление связи

    /* связывание */
    TSD3 sd21;
    TSD3 sd22(sf3);
    TSD3 sd23; sd23.Bind(sf3);
    TSD3 sd24; sd24.Bind(&A::sf3);
    TSD3 sd25; sd25.Bind(&B::sf3);
    TSD3 sd26; sd26.Bind(&a, &A::mf3);
    TSD3 sd27; sd27.Bind(&a, &A::cf3);
    TSD3 sd28; sd28.Bind(ac, &A::vf3);
    TSD3 sd29; sd29.Bind(&b, &B::mf3);
    TSD3 sd30; sd30.Bind(bc, &B::cf3);
    TSD3 sd31; sd31.Bind(ac, &A::vcf3);
    TSD3 sd32; sd32.Bind(bc, &B::vcf3);
    TSD3 sd33; sd33.Bind(sd31.GetMemFunc());
    TSD3 sd34 = sd32;
    TSD3 sd35; sd35.SetMemFunc(sd33.GetMemFunc());

    sdl.push_back(sd01), sdl.push_back(sd02), sdl.push_back(sd03), sdl.push_back(sd04), sdl.push_back(sd05);
    sdl.push_back(sd06), sdl.push_back(sd07), sdl.push_back(sd08), sdl.push_back(sd09), sdl.push_back(sd10);
    sdl.push_back(sd11), sdl.push_back(sd12), sdl.push_back(sd13), sdl.push_back(sd14), sdl.push_back(sd15);
    sdl.push_back(sd21), sdl.push_back(sd22), sdl.push_back(sd23), sdl.push_back(sd24), sdl.push_back(sd25);
    sdl.push_back(sd26), sdl.push_back(sd27), sdl.push_back(sd28), sdl.push_back(sd29), sdl.push_back(sd30);
    sdl.push_back(sd31), sdl.push_back(sd32), sdl.push_back(sd33), sdl.push_back(sd34), sdl.push_back(sd35);

    /* вызов функций */
    for (size_t n = 0; n < sdl.size(); n++) sdl[n](1,2,3);
    std::cout << std::endl << std::endl;

    /* TMultiDelegate - содержит неограниченное кол-во связей */
    /* конструкция (аналогично TSingleDelegate) */
    TMD3 md01;
    TMD3 md02(sf3);
    TMD3 md03 = sf3;
    TMD3 md04(&A::sf3);
    TMD3 md05 = &A::sf3;
    TMD3 md06 = &B::sf3;
    TMD3 md07(&a, &A::mf3);
    TMD3 md08(&a, &A::cf3);
    TMD3 md09(ac, &A::vf3);
    TMD3 md10(&b, &B::mf3);
    TMD3 md11(bc, &B::cf3);
    TMD3 md12(bc, &B::vf3);
    TMD3 md13(md10);
    TMD3 md14(sd11.GetMemFunc());
    TMD3 md15 = md12;

    /* связывание (аналогично TSingleDelegate, только каждый метод можно связывать сколько угодно раз) */
    TMD3 md21;
    TMD3 md22(sf3);
    TMD3 md23; md23.Bind(sf3);
    TMD3 md24; md24.Bind(&A::sf3);
    TMD3 md25; md25.Bind(&B::sf3);
    TMD3 md26; md26.Bind(&a, &A::mf3);
    TMD3 md27; md27.Bind(&a, &A::cf3);
    TMD3 md28; md28.Bind(ac, &A::vf3); md28.Bind(ac, &A::vf3);
    TMD3 md29; md29.Bind(&b, &B::mf3);
    TMD3 md30; md30.Bind(bc, &B::cf3); md30.Bind(bc, &B::cf3);
    TMD3 md31; md31.Bind(ac, &A::vcf3);
    TMD3 md32; md32.Bind(bc, &B::vcf3);
    TMD3 md33; md33.Bind(sd31.GetMemFunc());
    TMD3 md34 = md32;
    TMD3 md35;

    mdl.push_back(md01), mdl.push_back(md02), mdl.push_back(md03), mdl.push_back(md04), mdl.push_back(md05);
    mdl.push_back(md06), mdl.push_back(md07), mdl.push_back(md08), mdl.push_back(md09), mdl.push_back(md10);
    mdl.push_back(md11), mdl.push_back(md12), mdl.push_back(md13), mdl.push_back(md14), mdl.push_back(md15);
    mdl.push_back(md21), mdl.push_back(md22), mdl.push_back(md23), mdl.push_back(md24), mdl.push_back(md25);
    mdl.push_back(md26), mdl.push_back(md27), mdl.push_back(md28), mdl.push_back(md29), mdl.push_back(md30);
    mdl.push_back(md31), mdl.push_back(md32), mdl.push_back(md33), mdl.push_back(md34), mdl.push_back(md35);

    /* выполнение */
    for (size_t n = 0; n < mdl.size(); n++) mdl[n](1,2,3);
    std::cout << std::endl << std::endl;

    /////////////////////////////////////////////////////////////////////////////

    TMD3 md40(md24), md41, md42;
    md40.Bind(&B::sf3);                    //связывание статической функции (можно и через оператор)
    md40 += md26, md40 += md27, md40 += md28, md40 += md31, md40 += md32;    //связывание через оператор +=
    md40 -= md25;                                //удаление через оператор -=
    md41.Bind(md40);                        //добавление всех связей из другого делегата
    md42 = md41;                                //удаление текущих, добавление всех связей из другого делегата
    md40 -= sf3;                                    //удаление статической функции через оператор -=
    md40.Unbind(ac, &A::vcf3);    //удаление метода
    md40 += sd23.GetMemFunc();    //связывание метода из TSingleDelegate через анонимный указатель (TMemFunc)
    md40 -= sd26.GetMemFunc();        //удаление метода из TSingleDelegate через анонимный указатель (TMemFunc)
    md42.Length();                            //кол-во всех связей
    md42.Clear();                                //удаление всех связей
    //Bind(); Unbind(); операторы +=, -= возвращают общее кол-во связей

    md40(1,2,3);    //вызов всех-всех связей в порядке добавления
    std::cout << std::endl;

    if (!md41.IsEmpty()) md41.Invoke(1,2,3);    //проверка на наличие связей, вызов всех связей
    std::cout << std::endl;

    md41 -= md40;                                    //удаление всех связей md40 из md41
    if (md41) md41.Invoke(1,2,3);    //проверка на наличие связей, вызов что осталось
    std::cout << std::endl;

    /* сравнение */
    if (sd11 < sd12) std::cout << "sd11 < sd12" << std::endl;
    std::cout << "sd05" << (sd05 == sd06 ? " == " : " != ") << "sd06" << std::endl;
    std::cout << "md41" << (md41 == md40 ? " == " : " != ") << "md40" << std::endl;
    std::cout << std::endl;
    
}
делегаты
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.