|
Программирование >> Инициализация объектов класса, структура
/ / простеая форма класса объекта-функции class less equal ten { public: bool operator() ( int val ) { return val <= 10; } некоторое значение меньше или равно 10: Теперь такой объект-функцию можно использовать точно так же, как предопределенный. Вызов алгоритма count if() с помощью нашего объекта-функции выглядит следующим образом: count if( vec.begin(), vec.end(), less equal ten() ); Разумеется, возможности этого класса весьма ограничены. Попробуем применить count if( vec.begin(), vec.end(), отрицатель, чтобы подсчитать, сколько в контейнере элементов, больших 10: not1(less eal then ())); или обобщить реализацию, разрешив пользователю задавать значение, с которым надо сравнивать каждый элемент контейнера. Для этого достаточно ввести в класс член для хранения такого значения и реализовать конструктор, инициализирующий данный член class less equal value { public: less equal value( int val ) : val( val ) {} bool operator() ( int val ) { return val <= val; } private: int val; указанной пользователем величиной: }; Новый объект-функция применяется для задания произвольного целого значения. Например, при следующем вызове подсчитывается число элементов, меньших или равных 25: count if( vec.begin(), vec.end(), less eal value( 25 )); Разрешается реализовать класс и без конструктора, если параметризовать его значением, с которым производится сравнение: В самой простой форме определение класса объекта-функции сводится к перегрузке оператора вызова. Вот, например, унарный объект-функция, определяющий, что template < int val > class less equal value { public: bool operator() ( int val ) { return val <= val; } Вот как надо было бы вызвать такой класс для подсчета числа элементов, меньших или равных 25: count if( vec.begin(), vec.end(), less eal value<25>()); (Другие примеры определения собственных объектов-функций можно найти в Приложении.) Упражнение 12.4 Используя предопределенные объекты-функции и адаптеры, создайте объекты-функции для решения следующих задач: (a) Найти все значения, большие или равные 1024. (b) Найти все строки, не равные pooh . (c) Умножить все значения на 2. Упражнение 12.5 Определите объект-функцию для возврата среднего из трех объектов. Определите функцию для выполнения той же операции. Приведите примеры использования каждого объекта непосредственно и путем передачи его функции. Покажите, в чем сходство и различие этих решений. 12.4. Еще раз об итераторах Следующая реализация шаблона функции не компилируется. Можете ли вы сказать, в таком виде это не компилируется template < typename type > count( const vector< type > &vec, type value ) { int count = 0; vector< type >::iterator iter = vec.begin(); while ( iter != vec.end() ) if ( *iter == value ) ++count; return count; почему? Проблема в том, что у ссылки vec есть спецификатор const, а мы пытаемся связать с ней итератор без такого спецификатора. Если бы это было разрешено, то ничто не помешало бы нам модифицировать с помощью этого итератора элементы вектора. Для vector< int >::iterator iter0 = vec0.begin(); vec1 - константный итератор: vector< int >::const iterator iter1 = vec1.begin(); Разумеется, присваивание константному итератору неконстантного разрешено всегда. правильно: инициазация константного итератора неконстантна Например: vector< int >::const iterator iter2 = vec0.begin(); 12.4.1. Итераторы вставки Вот еще один фрагмент программы, в котором есть тонкая, но серьезная ошибка. Видите int ia[] = { 0, 1, 1, 2, 3, 5, 5, 8 }; vector< int > ivec( ia, ia+8 ), vres; ... поведение программе! во время волнения не определено ли вы, в чем она заключается? unique copy( ivec.begin(), ivec.end(), vres.begin() ); предотвращения подобной ситуации язык требует, чтобы итератор, связанный с const- правильно: это компилируется без ошибок вектором, был константным. Мы можем сделать это следующим образом: vector< type>::const iterator iter = vec.begin(); Требование, чтобы с const-контейнером был связан только константный итератор, аналогично требованию о том, чтобы const-массив адресовался только константным указателем. В обоих случаях это вызвано необходимостью гарантировать, что содержимое const-контейнера не будет изменено. Операции begin() и end() перегружены и возвращают константный или неконстантный итератор в зависимости от наличия спецификатора const в объявлении контейнера. Если vector< int > vec0; дана такая пара объявлений: const vector< int > vec1; то при обращениях к begin() и end() для vec0 будет возвращен неконстантный, а для
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |