Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Саттер Герб. Стандарты программирования на С++. 101 правило и рекомендация - royallib.ru.doc
Скачиваний:
58
Добавлен:
11.03.2016
Размер:
715.24 Кб
Скачать

89. Корректно пишите функциональные объекты Резюме

Разрабатывайте функциональные объекты так, чтобы их копирование выполнялось как можно эффективнее. Там, где это возможно, делайте их максимально адаптируемыми путем наследования от unary_function или binary_function.

Обсуждение

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

template<class InputIter, class Func>

Function for_each(InputIter first, InputIter last, Function f);

Следовательно, функциональные объекты должны легко копироваться и быть мономорфными (для защиты от срезки), так что избегайте виртуальных функций (см. рекомендацию 54). Конечно, у вас могут быть большие и/или полиморфные функциональные объекты — их тоже вполне можно использовать; просто скройте их размер с помощью идиомы Pimpl (указателя на реализацию; см. рекомендацию 43). Эта идиома позволяет, как и требуется, получить внешний мономорфный класс малого размера, обеспечивающий доступ к богатой функциональности. Внешний класс должен удовлетворять следующим условиям.

• Быть адаптируемым. Наследуйте его от unary_function или binary_function.

• Использовать идиому Pimpl. Такой класс содержит указатель (например, shared_ptr) на (возможно, большого размера) реализацию необходимой функциональности.

• Иметь оператор(ы) вызова функции. Эти операторы передают вызовы объекту-реализации.

Этим ограничиваются требования к внешнему классу (не считая возможного наличия собственных (не генерируемых компилятором) конструкторов, оператора присваивания и/или деструктора.

Функциональные объекты должны быть адаптируемы. Стандартные связыватели и адаптеры полагаются на наличие определенных инструкций typedef, обеспечить которые легче всего при наследовании ваших функциональных объектов от unary_function или binary_function. Инстанцируйте unary_function или binary_function с теми типами, которые получает и возвращает ваш оператор operator() (при этом у каждого типа, не являющегося указателем, следует убрать все спецификаторы const верхнего уровня, а также все &).

Постарайтесь избежать наличия нескольких операторов operator(), поскольку это затрудняет адаптируемость. Дело в том, что обычно оказывается невозможно обеспечить корректные инструкции typedef, необходимые для адаптирования, поскольку один и тот же синоним типа, определяемый через инструкцию typedef, имеет разные значения для разных операторов operator().

Не все функциональные объекты являются предикатами — предикаты представляют собой подмножество функциональных объектов (см. рекомендацию 87).

Ссылки

[Allison98] §15, §C • [Austern99] §4, §8, §15 • [Gamma95] Bridge • [Josuttis99] §8.2.4 • [Koenig97] §21, §29 • [Meyers97] §34 • [Meyers01] §38, §40, §46 • [Musser01] §2.4, §8, §23 • [Sutter00] §26-30 • [Vandevoorde03] §22

Безопасность типов

Если вы лжете компилятору, он будет мстить.

Генри Спенсер (Henry Spencer)

Всегда будут вещи, которые мы будем хотеть сказать в наших программах и которые трудно сформулировать на любом языке программирования.

Алан Перлис (Alan Perlis)

Последней (не по важности) темой книги является корректность типов — очень важное свойство программ, которое вы должны изо всех сил стараться поддерживать. Теоретически корректная с точки зрения типов функция не может обратиться к нетипизированной памяти или вернуть неверные значения. На практике, если ваш код поддерживает корректность типов, он тем самым избегает большого количества неприятных ошибок, от непереносимости программ до порчи содержимого памяти и неопределенного поведения программ.

Основная идея поддержки корректности типов — всегда считывать информацию в том формате, в котором она была записана. Иногда С++ позволяет легко нарушить это правило; приведенные в этом разделе рекомендации помогут вам избежать подобных ошибок.

В этом разделе мы считаем наиболее значимой рекомендацию 91 — "Работайте с типами, а не с представлениями". Система типов — ваш друг и верный союзник. Воспользуйтесь ее помощью и попытайтесь не злоупотреблять ее доверием.