Kód Delegáti v CPP
Z CHWiki
Implementace delegátu v C++. Nejde o to, aby byly přesně jako v C#, ale aby se jim co nejvíce podobaly. Další výhodou je, že je možné mít v delegátovi jak standardní funkce, tak i metody. Bohužel neumožňují mít ve funkci víc jak 1 parametr. Na konci je příklad použití.
[editovat] Zdrojový kód
#pragma once
// Tady si muzes priradit vlastni typ pointeru pro potomky tridy ICall
// Napr.: #define _DELEG_PTR_TYPE(type) CSmartPointer< type >
#define _DELEG_PTR_TYPE(type) type*
// Zde si nastav tridu, ze ktere bude ICall dedit
// Napr.: #define _DELEG_CALL_INHERIT : public CSharedObject
#define _DELEG_CALL_INHERIT
// Tohle zakomentuj, pokud nechces, aby se na pointery volalo delete
#define _DELEG_ALLOW_DELETE
/**
Obecna funkce s parametrem
**************************************************************************************************/
template<class Param = void>
class ICall _DELEG_CALL_INHERIT
{
public:
virtual void Call(Param) = 0;
};
/**
Ukazatel na funkci s volitelnym parametrem
**************************************************************************************************/
template<class Param = void>
class CFunctionCall : public ICall<Param>
{
public:
typedef void (*FUNC)(Param);
CFunctionCall(const FUNC f): m_f(f) {}
virtual void Call(Param p) { return m_f(p); }
private:
FUNC m_f;
};
/**
Ukazatel na funkci specializovany pro parametr void
**************************************************************************************************/
template<>
class CFunctionCall<void> : public ICall<void>
{
public:
typedef void (*FUNC)();
CFunctionCall(const FUNC f): m_f(f) {}
virtual void Call() { return m_f(); }
private:
FUNC m_f;
};
/**
Ukazatel na metodu s volitelnym parametrem
**************************************************************************************************/
template<class T, class Param = void>
class CMethodCall : public ICall<Param>
{
public:
typedef void (T::*FUNC)(Param);
CMethodCall(T *obj, const FUNC f): m_obj(obj), m_f(f) {}
virtual void Call(Param p) { return (m_obj->*m_f)(p); }
private:
T *m_obj;
FUNC m_f;
};
/**
Ukazatel na metodu specializovany pro parametr void
**************************************************************************************************/
template<class T>
class CMethodCall<T, void> : public ICall<void>
{
public:
typedef void (T::*FUNC)();
CMethodCall(T *obj, const FUNC f): m_obj(obj), m_f(f) {}
virtual void Call() { return (m_obj->*m_f)(); }
private:
T *m_obj;
FUNC m_f;
};
/**
Delegat - zapoudruje pole obecnych ukazatelu na funkci
Inspirovano z C#.
**************************************************************************************************/
template<class Param = void>
class CDelegate
{
public:
typedef _DELEG_PTR_TYPE(ICall<Param>) PCall;
#ifdef _DELEG_ALLOW_DELETE
~CDelegate() { Clear(); }
#endif
void Clear()
{
#ifdef _DELEG_ALLOW_DELETE
for (std::vector<PCall>::iterator it = m_list.begin(); it != m_list.end(); it++)
delete *it;
#endif
m_list.clear();
}
void operator +=(PCall call) { m_list.push_back(call); }
void operator -=(PCall call) { m_list.remove(call); }
void operator ()(Param p)
{
for (std::vector<PCall>::iterator it = m_list.begin(); it != m_list.end(); it++)
(*it)->Call(p);
}
private:
std::vector<PCall> m_list;
};
/**
Delegat specializovany na parametr void
**************************************************************************************************/
template<>
class CDelegate<void>
{
public:
typedef _DELEG_PTR_TYPE(ICall<>) PCall;
#ifdef _DELEG_ALLOW_DELETE
~CDelegate() { Clear(); }
#endif
void Clear()
{
#ifdef _DELEG_ALLOW_DELETE
for (std::vector<PCall>::iterator it = m_list.begin(); it != m_list.end(); it++)
delete *it;
#endif
m_list.clear();
}
void operator +=(PCall call) { m_list.push_back(call); }
void operator -=(PCall call) { m_list.remove(call); }
void operator ()()
{
for (std::vector<PCall>::iterator it = m_list.begin(); it != m_list.end(); it++)
(*it)->Call();
}
private:
std::vector<PCall> m_list;
};
[editovat] Použití bez parametru
void moje_funkce() {}
class Trida
{
public:
void Metoda() {}
};
int main(...)
...
CDelegate<> deleg;
deleg += new CFunctionCall<>(moje_funkce);
deleg += new CMethodCall<Trida>(&Instance, &Trida::Metoda);
deleg(); // Zavola vsechny funkce
...
[editovat] Použití s libovolným parametrem (v tomto případě int)
void moje_funkce(int a) {}
class Trida
{
public:
void Metoda(int a) {}
};
int main(...)
...
CDelegate<int> deleg;
deleg += new CFunctionCall<int>(moje_funkce);
deleg += new CMethodCall<Trida, int>(&Instance, &Trida::Metoda);
deleg(10); // Zavola vsechny funkce
...
