|
Программирование >> Многопоточная библиотека с принципом минимализма
ции, не связанной с набором. Здесь в действие вступает сцепление, реализованное в классе Functor. По мере того как пользователь вводит все новые и новые символы, создаются все новые и новые функторы. Таким образом, возникает возможность выполнить последовательность нажатий клавиш как одну операцию. Функция-член Document: :lnsertchar, по существу, заталкивает функтор в стек отката. Когда пользователь выбирает пункт меню Undo, этот функтор должен быть выполнен и затолкнут в стек повтора операций. Как видим, связывание аргументов и сцепление позволяют нам работать с функторами единообразно: вид вызова не имеет значения, поскольку он скрыт внутри функтора. Это значительно облегчает задачу реализации операций отката и повтора операций. 5.15. Резюме Использовать хорошие библиотеки на языке С++ намного легче, чем создавать. С другой стороны, разрабатывать библиотеки очень интересно. Оглядываясь на детали описанных выше реализаций, можно извлечь несколько уроков, касающихся создания обобщенных профамм. Создавайте гибкие шаблонные типы. Сфемитесь на все смофеть с максимально общей точки зрения. Классы FunctorHandl ег и MemFunHandl ег приобрели много преимуществ, благодаря тому, что в них используются шаблоны. Указатели на функции предоставляют большую свободу. По сравнению с их функциональными возможностями получающийся код имеет удивительно небольшой размер. Все эти выгоды достигаются благодаря использованию шаблонов и тому, что компилятору предоставлено право самому выводить типы, когда это возможно. Обобщенное профаммирование способствует созданию семантики первого класса (см. примечание в начале главы. - Прим. ред.). Было бы крайне зафуднительно оперировать исключительно указателями на класс Functorlmpl. Представьте себе, как в этих условиях реализуются связывание и сцепление. Изощренные технологии предназначены для достижения большей простоты. На основе всех этих шаблонов, наследования, связывания и управления памятью создана простая, легкая в применении и хорошо продуманная библиотека. В двух словах, класс Functor задерживает вызов функции, функтора или функции-члена. Он сохраняет вызываемый объект и предоставляет для его вызова оператор О. Ниже приведено краткое описание этого класса. 5.16. Краткое описание класса Functor Класс Functor является шаблонным и позволяет выражать вызовы функций, имеющих до 15 аргументов. Первым шаблонным парамефом является тип возвращаемого значения, вторым - список типов, содержащий типы парамефов функции. Третий шаблонный парамеф задает потоковую модель, которая используется механизмом распределения памяти, применяемым в классе Functor. Подробная информация о списках классов приведена в главе 3, о потоковой модели - в приложении, о механизме распределения памяти для небольших объектов - в главе 4. Объект класса Functor можно инициализировать функцией, функтором, другим объектом класса Functor или указателем на объект и указателем на метод, как показано в приведенном ниже примере. void Function(int) struct SomeFunctor void operatorOCint); truct SomeClass void MemberFunction(int); void exampleО инициализируем класс Functor функцией Functor<void, TYPELlST l(int)> cmdl(Function); инициализируем класс Functor функтором SomeFunctor fn; Functor<void, TYPELlST l(int)> cmd2(fn); инициализируем класс Functor указателем на объект и указателем на функцию-член SomeClass myobject; Functor<void, TYPELlST l(int)> cmd3(&myObject, &SomeClass:rMemberFunction); инициализируем класс Functor другим объектом класса Functor (копирование) Functor<void, TYPELlST l(int)> cmd4(cmd3); Объект класса Functor можно инициализировать объектом класса std::auto ptr< Functorimpl<r, TList> >. Это позволяет создавать расширения, определенные пользователем. Класс Functor поддерживает автоматические преобразования типов аргументов и возвращаемых значений. Например, в предыдущем примере функции-члены SomeFunctor::operatorO и SomeClass::MemberFunction могут получать аргументы типа double вместо аргументов типа int. При перегрузке функций-членов следует создавать дополнительный код для устранения неоднозначности. Класс Functor полностью поддерживает семантику первого класса: копирование, присваивание и передачу по значению. Класс Functor не является ни полиморфным, ни базовым. Если нужно расширить класс Functor, в качестве базового следует применять класс Functorlmpl. Класс Functor поддерживает связывание аргументов. Вызов шаблонной функции BindFirst связывает первый аргумент с фиксированным значением. В результате возникает параметризованный класс Functor, параметрами которого являются остальные аргументы. Рассмотрим пример. void f() определяем класс Functor с тремя аргументами Functor<void, TYPELiST 3(int, int, double)> cmdl( someEntity); Связываем первый аргумент с числом 10 Functor<void, TYPELlST 2(int, double)> cmd2( BindFirst(cmdl, 10); Эквивалентно вызову cmdlClO, 20, 5.6) cmd2C20, 5.6) Используя функцию chain, в одном объекте класса Functor можно сцепить несколько объектов этого класса. void fO { Functoro cmdlCsomething); Functoro cmd2CsomethingElse); Сцепливаем объекты cmdl и cmd2 в контейнер Functoro cmd3(chain(cmdl, cmd2)); Эквивалентно cmdlQ; cmd2C); ctndBQ; Затраты, связанные с использованием простых объектов класса Functor, состоят из одной переадресации (вызова через указатель). При каждом связывании или сцепливании возникает один дополнительный виртуальный вызов. Параметры копируются только при необходимости преобразования типов. Шаблонный класс Functorlmpl использует механизм распределения памяти для небольших объектов, описанный в главе 4.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |