Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
larger_than_v);
if (p!=v.end()) { /* мы нашли значение, превышающее 31 */ }
v_val = x; // устанавливаем переменную v_val равной x
// для следующего вызова предиката larger_than_v
list<double>::iterator q = find_if(v.begin(), v.end(),
larger_than_v);
if (q!=v.end()) { /* мы нашли значение, превышающее x*/ }
// ...
}

ПОПРОБУЙТЕ
Почему такое использование переменной v вызывает у нас такое отвращение? Назовите по крайней мере три способа, которые приведут к непонятным ошибкам. Назовите три приложения, в которых такие программы особенно недопустимы.
21.4. Объекты-функции
Итак, мы хотим передавать предикат алгоритму find_if() и чтобы этот предикат сравнивал элементы со значением, которое мы зададим как его аргумент. В частности, мы хотим написать примерно такой код:
void f(list<double>& v, int x)
{
list<double>::iterator p = find_if(v.begin(), v.end(),
Larger_than(31));
if (p!=v.end()) { /* мы нашли число, превышающее 31 */ }
list<double>::iterator q = find_if(v.begin(), v.end(),
Larger_than(x));
if (q!=v.end()) { /* мы нашли число, превышающее x */ }
// ...
}
Очевидно, что функция Larger_than должна удовлетворять двум условиям.
• Ее можно вызывать как предикат, например pred(*first).
• Она может хранить значение, например 31 или x, передаваемое при вызове.

class Larger_than {
int v;
public:
Larger_than(int vv) : v(vv) { } // хранит аргумент
bool operator()(int x) const { return x>v; } // сравнение
};
Следует отметить, что это определение представляет собой именно то, что мы требовали от предиката. Теперь осталось понять, как это работает. Написав выражение Larger_than(31), мы (очевидно) создаем объект класса Larger_than, хранящий число 31 в члене v. Рассмотрим пример.
find_if(v.begin(),v.end(),Larger_than(31))
Здесь мы передаем объект Larger_than(31) алгоритму find_if() как параметр с именем pred. Для каждого элемента v алгоритм find_if() осуществляет вызов
pred(*first)
Это активизирует оператор вызова функции, т.е. функцию-член operator(), для объекта-функции с аргументом *first. В результате происходит сравнение значения элемента, т.е. *first, с числом 31.
Мы видим, что вызов функции можно рассматривать как результат работы оператора (), аналогично любому другому оператору. Оператор () называют также оператором вызова функции (function call operator) или прикладным оператором (application operator). Итак, оператор () в выражении pred(*first) эквивалентен оператору Larger_than::operator(), точно так же, как оператор [] в выражении v[i] эквивалентен оператору vector::operator[].
21.4.1. Абстрактная точка зрения на функции-объекты

class F { // абстрактный пример объекта-функции
S s; // состояние
public:
F(const S& ss):s(ss) { /* устанавливает начальное значение */ }
T operator() (const S& ss) const
{
// делает что-то с аргументом ss
// возвращает значение типа T (часто T — это void,
// bool или S)
}
const S& state() const { return s; } // демонстрирует
// состояние
void reset(const S& ss) { s = ss; } // восстанавливает
// состояние
};
Объект класса F хранит данные в своем члене s. По мере необходимости объект-функция может иметь много данных-членов. Иногда вместо фразы “что-то хранит данные” говорят “нечто пребывает в состоянии”. Когда мы создаем объект класса F, мы можем инициализировать это состояние. При необходимости мы можем прочитать это состояние. В классе F для считывания состояния предусмотрена операция state(), а для записи состояния — операция reset(). Однако при разработке объекта-функции мы свободны в выборе способа доступа к его состоянию.
Разумеется, мы можем прямо или косвенно вызывать объект-функцию, используя обычную систему обозначений. При вызове объект-функция F получает один аргумент, но мы можем определять объекты-функции, получающие столько параметров, сколько потребуется.


Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Гость Татьяна24 сентябрь 22:20 Как то не очень... Невеста по ошибке. Я не дам тебе развод - Майя Линн
-
Римма24 сентябрь 21:52 Почему главные героинитпкие идиотки? И сюжет не плохой, и написано хорошо. Но как героиня - так дура дурой.... Хозяйка маленького дома, или Любимая для дракона - Кира Рамис
-
Римма20 сентябрь 12:27 Много ненужных пояснений и отступлений. Весь сюжет теряет свою привлекательность. Героиня иногда так тупит, что читать не... Хозяйка приюта для перевертышей и полукровок - Елена Кутукова