Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А.
Нужно сделать так чтобы метод класса А вызывался классом В.
реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?
//// Functor.hclass 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;
}
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();
};
Здравствуйте, Аноним, Вы писали:
А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А. А>Нужно сделать так чтобы метод класса А вызывался классом В.
А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?
ну про boost::function уже сказали
а если можно сделать метод класса B шаблоном(или весь класс B), то все проще
// B.hstruct B
{
template < class TA, void (TA:: *fn )() >
void call( TA * pa )
{
(pa->*fn)();
}
};
// A.hstruct A
{
B b;
A()
{
b.call<A, &A::method>( this );
}
void method() { std::cout << "A::method()" << std::endl; }
};
Здравствуйте, Аноним, Вы писали:
А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А. А>Нужно сделать так чтобы метод класса А вызывался классом В.
А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?
А 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();
}
Здравствуйте, Аноним, Вы писали:
А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А. А>Нужно сделать так чтобы метод класса А вызывался классом В.
А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?
Тока надо не забыть delete m_pFunctor
Re: Реализация делегата
От:
Аноним
Дата:
19.09.07 16:40
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Есть класс А, и класс В. При этом класс В агрегируеться классом А, и класс В нифига не знает о классе А. А>Нужно сделать так чтобы метод класса А вызывался классом В.
А>реализовал я примерно вот так, но как-то сложно все вышло, может есть более элегантный способ?