C_DELEGATE‹TRet TEMPLATE_ARGS›& operator=(IDelegate* pDelegate) {

  RemoveAll();

  Add(pDelegate);

  return *this;

 }

 C_DELEGATE‹TRet TEMPLATE_ARGS›& operator+=(IDelegate* pDelegate) {

  Add(pDelegate);

  return *this;

 }

 C_DELEGATE‹TRet TEMPLATE_ARGS›& operator-=(IDelegate* pDelegate) {

  Remove(pDelegate);

  return *this;

 }

 TRet operator()(PARAMS) {

  return Invoke(ARGS);

 }

private:

 void Add(IDelegate* pDelegate) {

  if(pDelegate != NULL) m_DelegateList.push_back(pDelegate);

 }

 void Remove(IDelegate* pDelegate) {

  DelegateList::iterator it;

  for(it = m_DelegateList.begin(); it!= m_DelegateList.end(); ++it) {

   if((*it)-›Compare(pDelegate)) {

    delete (*it);

    m_DelegateList.erase(it);

    break;

   }

  }

 }

 void RemoveAll() {

  DelegateList::iterator it;

  for(it = m_DelegateList.begin(); it!= m_DelegateList.end(); ++it) delete (*it);

  m_DelegateList.clear();

 }

 TRet Invoke(PARAMS) {

  DelegateList::const_iterator it;

  for (it = m_DelegateList.begin(); it != --m_DelegateList.end(); ++it) (*it)-›Invoke (ARGS);

  return m_DelegateList.back()-›Invoke(ARGS);

 }

private:

 DelegateList m_DelegateList;

};

Вынеся обобщённый таким образом делегат в отдельный файл delegate_impl.h, мы можем сгенерировать его специализацию для любого количества параметров. Например, специализация делегата для пяти параметров получается так:

// 5 parameters…

#define SUFFIX 5

#define TEMPLATE_PARAMS

, class TP1, class TP2, class TP3, class TP4, class TP5

#define TEMPLATE_ARGS , TP1, TP2, TP3, TP4, TP5

#define PARAMS TP1 p1, TP2 p2, TP3 p3, TP4 p4, TP5 p5

#define ARGS p1, p2, p3, p4, p5

#include 'delegate_impl.h'

#undef SUFFIX

#undef TEMPLATE_PARAMS

#undef TEMPLATE_ARGS

#undef PARAMS

#undef ARGS

Подобные фрагменты для наборов от 0 до 10 параметров можно включить в отдельный файл delegate.h, который и будут подключать пользователи делегатов.

Вот пример использования библиотеки делегатов, которую мы только что получили. Обратите внимание, что он практически полностью соответствует примеру на языке C#, с которого началась эта статья.

#include ‹iostream›

#include ‹fstream›

#include ‹string›

using namespace std;

#include 'delegate.h'

class App {

public:

 // Определяем делегат Callback,

 // который принимает 1 параметр и ничего не возвращает.

 typedef CDelegate1‹void, string› Callback;

 // Это метод класса App.

 void OutputToConsole(string str) { cout ‹‹ str ‹‹ endl; }

 // А это статический метод класса App.

 static void OutputToFile(string str) {

  ofstream fout('output.txt', ios::out | ios::app);

  fout ‹‹ str ‹‹ endl; fout.close();

 }

};

int main() {

 App app;

 // Создаём делегат.

 App::Callback callback = NULL;

 if (!callback.IsNull()) callback('1');

 // Добавляем ссылку на OutputToFile.

Вы читаете Делегаты на C++
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×