Реализация делегата
От: Аноним  
Дата: 18.09.07 08:45
Оценка:
Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.
Нужно сделать так чтобы метод класса А вызывался классом В.

реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?


//// Functor.h

class Functor     /// <----- это базовый класс делегата
{
public:
    ....
    virtual void operator()()         = 0;
        .....
};

//// B.h
#include "Functor.h"

class B
{

public:

B (Functor *p) 
{
  m_pFunctor = p;
  (*m_pFunctor)();  /// тут выполняется делегированный метод

};

protected:
Functor *m_pFunctor;

}


//// A.h
#include "Functor.h"

class A
{
public:
A()
{
     b = new B( new InvFunctor(this) ); /// вот так собственно передается делегат
}
~A()
{
    delete b;
}

    void InvocedMethod() {};  //// <------  этот метод необходимо выполнить в классе В


protected:
       B *b;
}    

class InvFunctor : Functor    //// а вот и собственно реализация делегата
{
 public:
    InvFunctor ( A *a  )      { m_pA = a; }
    virtual void operator()() { if ( m_pA ) m_pA->InvocedMethod(); }

protected:
        A *m_pA;
}
Re: Реализация делегата
От: Sharp Eye Россия  
Дата: 18.09.07 09:29
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А> <skip>


ИМХО так нормально.


Можно ещё использовать интерфейс:


struct IA
{
    ...
    virtual void fn() = 0;
    ...
};

class B
{
    IA * a_;
public:
    B(IA * a) : a_(a)
    {
        a_->fn();
    }
};

class A : public IA
{
    B * b_;
public:
    A()
    {
        b_ = new B(this);
    }

    ~A()
    {
        delete b_;
    }

    virtual void fn();
};


Можно буст прикрутить:


typedef boost::function<void ()> Delegate;

class B
{
    Delegate delegate_;
public:
    B(const Delegate & delegate) : delegate_(delegate)
    {
        delegate_();
    }
};

class A
{
    B * b_;
public:
    A()
    {
        b_ = new B(boost::bind(&A::fn, this));
    }

    ~A()
    {
        delete b_;
    }

    virtual void fn();
};
Re: Реализация делегата
От: _Dreamer Россия  
Дата: 18.09.07 09:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.

А>Нужно сделать так чтобы метод класса А вызывался классом В.

А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?


ну про boost::function уже сказали
а если можно сделать метод класса B шаблоном(или весь класс B), то все проще
// B.h
struct B 
{
    template < class TA, void (TA:: *fn )() >
    void call( TA * pa )
    {
        (pa->*fn)();
    }
};

// A.h
struct A 
{
    B b;

    A() 
    {
        b.call<A, &A::method>( this );
    }

    void method() { std::cout << "A::method()" << std::endl; }
};
Re: Реализация делегата
От: dr.Chaos Россия Украшения HandMade
Дата: 18.09.07 09:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.

А>Нужно сделать так чтобы метод класса А вызывался классом В.

А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?


А std::mem_fun_ref() не подойдет?
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re: Реализация делегата
От: Аноним  
Дата: 18.09.07 11:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.

А>Нужно сделать так чтобы метод класса А вызывался классом В.

можно и так реализовать дело вкуса
struct Callback{
    virtual void operator()();
};

template<class C>
struct MemberCallback : public Callback
{   
     typedef void (C::*MemFun)();
     MemFun func;
     C* ptr;

     MemberCallback(C* instance, MemFun member)  :ptr(instance), func(member) { }
    
    virtual void operator()(){
        (ptr->*func)();
    }
};

template<class C>
MemberCallback<C> makeMemberCallback(C* instance, typename MemberCallback<C>::MemFun member) {
 return MemberCallback<C>(instance, member);
}

//
// собсно проверка
//

struct B{
  void foobar(Callback bc){ bc(); } //класс B знать не знает о наличии класса А
};

struct A{
  void d(){
     B b; b.foobar(makeMemberCallback(this, &A::d)); 
  }
};

int main(){
    A a; a.d();
}
Re: Реализация делегата
От: ansi  
Дата: 18.09.07 23:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.

А>Нужно сделать так чтобы метод класса А вызывался классом В.

А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?


Тока надо не забыть delete m_pFunctor
Re: Реализация делегата
От: Аноним  
Дата: 19.09.07 16:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.

А>Нужно сделать так чтобы метод класса А вызывался классом В.

А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?


Паттерн Observer (он же Publisher/Subscriber)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.