Делегаты на C++
Шрифт:
template‹class TObj›
class CMethodDelegateVoid: public IDelegateVoid {
public:
typedef void (TObj::*PMethod);
CMethodDelegateVoid(TObj* pObj, PMethod pMethod) {
m_pObj = pObj;
m_pMethod = pMethod;
}
virtual void Invoke {
(m_pObj-›*m_pMethod);
}
virtual bool Compare(IDelegateVoid* pDelegate);
private:
TObj *m_pObj;
PMethod m_pMethod;
};
template‹class TObj›
bool CMethodDelegateVoid‹TObj›::Compare(IDelegateVoid* pDelegate) {
CMethodDelegateVoid‹TObj›* pMethodDel = dynamic_cast‹CMethodDelegateVoid‹TObj›* ›(pDelegate);
if (pMethodDel == NULL || pMethodDel-›m_pObj != m_pObj || pMethodDel-›m_pMethod != m_pMethod) return false;
return true;
}
Классы CStaticDelegateVoid
IDelegateVoid* NewDelegate(void (*pFunc)) {
return new CStaticDelegateVoid(pFunc);
}
template ‹class TObj›
IDelegateVoid* NewDelegate(TObj* pObj, void (TObj::*pMethod)) {
return new CMethodDelegateVoid‹TObj› (pObj, pMethod);
}
Мы уже почти закончили. Осталось написать объектную обёртку над интерфейсом IDelegateVoid, которая будет поддерживать список указателей и определять набор операторов, аналогичных используемым в C# - operator=, operator, operator+= и operator-=. Для простоты будем использовать стандартный класс std::list для хранения списка указателей.
#include ‹list›
class CDelegateVoid {
public:
CDelegateVoid(IDelegateVoid* pDelegate = NULL) {
Add(pDelegate);
}
~CDelegateVoid { RemoveAll; }
bool IsNull { return (m_DelegateList.size == 0); }
CDelegateVoid& operator=(IDelegateVoid* pDelegate) {
RemoveAll;
Add(pDelegate);
return *this;
}
CDelegateVoid& operator+=(IDelegateVoid* pDelegate) {
Add(pDelegate);
return *this;
}
CDelegateVoid& operator-=(IDelegateVoid* pDelegate) {
Remove(pDelegate);
return *this;
}
void operator { Invoke; }
private:
void Add(IDelegateVoid* pDelegate);
void Remove(IDelegateVoid* pDelegate);
void RemoveAll;
void Invoke;
private:
std::list‹IDelegateVoid*› m_DelegateList;
};
Для
void CDelegateVoid::Add(IDelegateVoid* pDelegate) {
if (pDelegate != NULL) m_DelegateList.push_back(pDelegate);
}
Метод Remove ищет в списке делегат, ссылающийся на заданную функцию, и в случае обнаружения удаляет его:
void CDelegateVoid::Remove(IDelegateVoid* pDelegate) {
std::list‹IDelegateVoid*›::iterator it;
for(it = m_DelegateList.begin; it!= m_DelegateList.end; ++it) {
if((*it)-›Compare(pDelegate)) {
delete (*it);
m_DelegateList.erase(it);
break;
}
}
delete pDelegate;
}
Метод RemoveAll просто очищает список, удаляя из него все делегаты:
void CDelegateVoid::RemoveAll {
std::list‹IDelegateVoid*›::iterator it;
for(it = m_DelegateList.begin; it != m_DelegateList.end; ++it) delete (*it);
m_DelegateList.clear;
}
Наконец, метод Invoke вызывает все функции и методы, на которые ссылаются делегаты из списка:
void CDelegateVoid::Invoke {
std::list‹IDelegateVoid*›::const_iterator it;
for (it = m_DelegateList.begin; it != m_DelegateList.end; ++it) (*it)-›Invoke;
}
Использовать полученный класс делегата можно примерно так.
Поделиться:
Популярные книги
Измена. Тайный наследник
1. Тайный наследник
Фантастика:
фэнтези
5.00
рейтинг книги
Инквизитор Тьмы
1. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Наследник
3. Династия
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Ротмистр Гордеев 3
3. Ротмистр Гордеев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
(Не)нужная жена дракона
5. Хроники Драконьей империи
Любовные романы:
любовно-фантастические романы
6.89
рейтинг книги
Идеальный мир для Лекаря 28
28. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Сыночек в награду. Подари мне любовь
1. Суровые отцы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Инквизитор Тьмы 2
2. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Генерал Скала и ученица
2. Генерал Скала и Лидия
Любовные романы:
любовно-фантастические романы
6.30
рейтинг книги
Искатель 1
1. Валинор
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Сердце Дракона. Том 10
10. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.14
рейтинг книги
Печать мастера
6. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
фэнтези
6.00
рейтинг книги
Выстрел на Большой Морской
4. Сыщик Его Величества
Детективы:
исторические детективы
полицейские детективы
8.64
рейтинг книги
Кодекс Крови. Книга VII
7. РОС: Кодекс Крови
Фантастика:
боевая фантастика
попаданцы
аниме
5.00