Вход/Регистрация
Делегаты на C++
вернуться

Шаргин Александр

Шрифт:

#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.

 // Вызываем её через делегата.

 callback += NewDelegate(App::OutputToFile);

 if (!callback.IsNull) callback("2");

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

 // Вызывается вся цепочка:

 // сначала OutputToFile, потом OutputToConsole.

 callback += NewDelegate(&app, &App::OutputToConsole);

 if (!callback.IsNull) callback("3");

 // Убираем ссылку на OutputToFile.

 // Вызывается только OutputToConsole.

 callback -= NewDelegate(App::OutputToFile);

 if (!callback.IsNull) callback("4");

 // Убираем оставшуюся ссылку на OutputToConsole.

 callback -= NewDelegate(&app, &App::OutputToConsole);

 if (!callback.IsNull) callback("5");

}

Законченный проект Visual Studio 7.0, содержащий этот пример, можно найти на сопровождающем компакт-диске.

Те же и Visual C++ 6.0

На этом можно было бы поставить точку, но остаётся ещё одна нерешённая проблема. Если вы попытаетесь скомпилировать приведённый пример в Visual C++ 6.0, у этого компилятора возникнут проблемы при задании параметра шаблона делегата TRet=void. Дело в том, что в этом случае VC6 не может корректно обработать конструкцию вида:

virtual TRet Invoke(TP1 p1) {

 // VC6 полагает, что нельзя возвращать выражение типа void.

 return (m_pObj-›*m_pMethod)(p1);

}

Данная конструкция совершенно законна в соответствии с пунктом 6.6.3/3 Стандарта языка C++. Но VC6 об этом не знает. Поэтому нам придётся искать обходные пути. Чтобы обойти эту недоработку компилятора, необходимо отдельно реализовать все классы CDelegateX для случая TRet=void. Идеальным инструментом для этой цели служит частичная специализация шаблонов, но VC6 не поддерживает и эту возможность языка C++. В результате решение задачи на VC6 превращается в занимательную головоломку.

  • Читать дальше
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: