Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

Эффективное использование STL. Библиотека программиста - Мейерс С.

Мейерс С. Эффективное использование STL. Библиотека программиста — Спб.: Питер , 2002. — 224 c.
ISBN 5-94723-382-7
Скачать (прямая ссылка): effektivnoeispolzovaniestlbibliote2002.djvu
Предыдущая << 1 .. 74 75 76 77 78 79 < 80 > 81 82 83 84 85 86 .. 114 >> Следующая

"Объявляйте operatorO константным в предикатных классах", но этой
формулировки недостаточно. Даже константные функции могут обращаться к
mutabl е-переменным, неконстантным локальным статическим объектам,
неконстантным статическим
Совет 40 157
объектам класса, неконстантным объектам в области видимости пространства
имен и неконстантным глобальным объектам. Хорошо спроектированный
предикатный класс должен обеспечить независимость функций operatorO и от
этих объектов. Объявление константных функций operatorO в предикатных
классах необходимо для правильного поведения, но не достаточно. Правильно
написанная функция operatorO является константной, но это еще не все. Она
должна быть "чистой" функцией.
Ранее в этом совете уже упоминалось о том, что всюду, где STL ожидает
получить предикатную функцию, может передаваться либо реальная функция,
либо объект предикатного класса. Этот принцип действует в обоих
направлениях. В любом месте, где STL рассчитывает получить объект
предикатного класса, подойдет и предикатная функция (возможно,
модифицированная при помощи ptr fun - см. совет 41). Теперь вы знаете,
что функции operatorO в предикатных классах должны быть "чистыми"
функциями, поэтому ограничение распространяется и на предикатные функции.
Следующая функция также плоха в качестве предиката, как и объекты,
созданные на основе класса BadPredicate:
bool anotherBadPredicate(const Widgets.const WidgetS)
{
static int timesCalled = 0: // Нет! Нет! Нет! Нет! Нет! Нет!
return ++timesCalled == 3: // Предикаты должны быть "чистыми"
} // функциями, а "чистые" функции
// не имеют состояния
Как бы вы ни программировали предикаты, они всегда должны быть "чистыми"
функциями.
Совет 40. Классы функторов должны быть адаптируемыми
Предположим, у нас имеется список указателей Widget* и функция, которая
по указателю определяет, является ли объект Widget "интересным":
list<Widget*> WidgetPtrs:
bool isInteresting(const Widget *pw):
Если потребуется найти в списке первый указатель на "интересный" объект
Widget, это делается легко:
1i st<Wi dget*>::i terator i =find_i f(wi dgetPtrs.begi n().wi
dgetPtrs.end(),
islnteresting);
if (i!=widgetPtrs.end()) {
// Обработка первого "интересного"
} // указателя на Widget
С другой стороны, если потребуется найти первый указатель на
"неинтересный" объект Widget, следующее очевидное решение не
компилируется:
list<Widget*>::iterator i = fi nd_i f(wi dgetPtrs.begi n(),wi
dgetPtrs.end(),
notl(islnteresting)); // Ошибка! He компилируется
158 Глава б • Функции, функторы и классы функций
Перед notl к функции islnteresting необходимо применить ptr_fun:
list<Widget*>::iterator i = fi nd_i f(wi dgetPtrs.begi n(),wi
dgetPtrs.end(),
notl(ptr_fun(isInteresting))); // Нормально
if (i!=widgetPtrs.end()){
// Обработка первого } // "неинтересного" указателя
//на Widget
При виде этого решения невольно возникают вопросы. Почему мы должны
применять ptr_fun к islnteresting перед notl? Что ptrfun для нас делает и
почему начинает работать приведенная выше конструкция?
Ответ оказывается весьма неожиданным. Вся работа ptr_fun сводится к
предоставлению нескольких определений типов. Эти определения типов
необходимы для notl, поэтому применение notl к ptr_fun работает, а
непосредственное применение notl к islnteresting не работает. Примитивный
указатель на функцию islnteresting не поддерживает определения типов,
необходимые для notl.
Впрочем, notl - не единственный компонент STL, предъявляющий подобные
требования. Все четыре стандартных адаптера (notl, not2, bindlst и
bind2nd), а также все нестандартные STL-совместимые адаптеры из внешних
источников (например, входящие в SGI и Boost - см. совет 50), требуют
существования некоторых определений типов. Объекты функций,
предоставляющие необходимые определения типов, называются адаптируемыми;
при отсутствии этих определений объект называется неадаптируемым.
Адаптируемые объекты функций могут использоваться в контекстах, в которых
невозможно использование неадаптируе-мых объектов, поэтому вы должны по
возможности делать свои объекты функций адаптируемыми. Адаптируемость не
требует никаких затрат, но значительно упрощает использование классов
функторов клиентами.
Наверное, вместо туманного выражения "некоторые определения типов" вы бы
предпочли иметь точный список? Речь идет об определениях argument_type,
fi rst_argument_type, second_argument_type и resul t_type, но ситуация
осложняется тем, что разные классы функторов должны предоставлять разные
подмножества этих имен. Честно говоря, если вы не занимаетесь разработкой
собственных адаптеров, вам вообще ничего не нужно знать об этих
определениях. Как правило, определения наследуются от базового класса, а
говоря точнее - от базовой структуры. Для классов функторов, у которых
operatorO вызывается с одним аргументом, в качестве предка выбирается
структура std: :unary_function. Классы функторов, у которых operatorO
Предыдущая << 1 .. 74 75 76 77 78 79 < 80 > 81 82 83 84 85 86 .. 114 >> Следующая