Делегаты на C++ - [7]

Шрифт
Интервал

> }

> 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:

> TRet Invoke(PARAMS) {

>  DelegateList::const_iterator it;

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

>  return static_cast‹IDelegate*› (m_DelegateList.back())-›Invoke(ARGS);

> }

>};


Обратите внимание на появившиеся приведения типов. В данном случае они никак не сказываются на типобезопасности делегатов, так как в списке m_DelegateList могут храниться только указатели на объекты классов CStaticDelegateX и CMethodDelegateX, а эти указатели заведомо приводятся к указателю на IDelegate.

В заключение несколько слов о проблеме производительности. Как уже говорилось, она может возникать из-за распределения объектов делегатов в куче. К сожалению, реализовать делегаты как стековые объекты не представляется возможным, так как для них существенным свойством является полиморфное поведение. Но и тут ситуацию можно существенно улучшить. Поскольку все делегаты централизованно создаются внутри функции NewDelegate, для них вполне возможно написать специализированный аллокатор, который будет распределять память для делегатов быстро и эффективно. Написание такого аллокатора оставляется читателю в качестве упражнения.

Заключение

Хочется отметить, что рассмотренный нами пример реализации делегатов может служить иллюстрацией как сильных, так и слабых сторон языка C++. Слабая сторона C++ - это его сложность. Особенно хорошо она заметна при реализации библиотек на базе шаблонов. Их код трудно читать и ещё труднее писать, так как в них семантическая сложность усугубляется сложностью синтаксической. Сильной же стороной C++ является совершенно невероятная гибкость этого языка. В рамках C++ можно реализовать и бесшовно интегрировать в язык самые разные возможности. Причём сделать это удаётся даже несмотря на грубейшие ошибки и недоработки разработчиков некоторых компиляторов.


Комментарии:

наследование операторов

›Дело в том, что в языке C++ операторы не наследуются.

Это не верно по крайней мере для MSVC++. Более того этот метод используется при написании функтора из библиотеки Loki http://fara.cs.uni-potsdam.de/~kaufmann/?page=lokiport (файл Functor.h), см. также http://www.geocities.com/rani_sharoni/LokiPort.html (VC7) и конечно оригинал http://moderncppdesign.com/

>#include ‹stdio.h›

>int main() {

> struct base {

>  void operator()(int x) { printf("void base::operator()(%d)\n",x); }

> };

> struct derived: base {};

> derived()(5);

> return 0;

>}

yaroslav_v 1.5.2003 9:55

Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.