Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
8
Добавлен:
14.08.2019
Размер:
7.54 Mб
Скачать

15.4. Оператор взятия индекса

Оператор взятия индекса operator[]() можно определять для классов, представляющих абстракцию контейнера, из которого извлекаются отдельные элементы. Примерами таких контейнеров могут служить наш класс String, класс IntArray, представленный в главе 2, или шаблон класса vector, определенный в стандартной библиотеке C++. Оператор взятия индекса обязан быть функцией-членом класса.

У пользователей String должна иметься возможность чтения и записи отдельных символов члена _string. Мы хотим поддержать следующий способ применения объектов данного класса:

String entry( "extravagant" );

String mycopy;

for ( int ix = 0; ix < entry.size(); ++ix )


mycopy[ ix ] = entry[ ix ];

Оператор взятия индекса может появляться как слева, так и справа от оператора присваивания. Чтобы быть в левой части, он должен возвращать l-значение индексируемого элемента. Для этого мы возвращаем ссылку:

#include <cassert>

inine char&

String::operator[]( int elem ) const

{

assert( elem >= 0 && elem < _size );

return _string[ elem ];


}

В следующем фрагменте нулевому элементу массива color присваивается символ 'V':

String color( "violet" );


color[ 0 ] = 'V';

Обратите внимание, что в определении оператора проверяется выход индекса за границы массива. Для этого используется библиотечная C-функция assert(). Можно также возбудить исключение, показывающее, что значение elem меньше 0 или больше длины C-строки, на которую ссылается _string. (Возбуждение и обработка исключений обсуждались в главе 11.)

15.5. Оператор вызова функции

Оператор вызова функции может быть перегружен для объектов типа класса. (Мы уже видели, как он используется, при рассмотрении объектов-функций в разделе 12.3.) Если определен класс, представляющий некоторую операцию, то для ее вызова перегружается соответствующий оператор. Например, для взятия абсолютного значения числа типа int можно определить класс absInt:

class absInt {

public:

int operator()( int val ) {

int result = val < 0 ? -val : val;

return result;

}


};

Перегруженный оператор operator() должен быть объявлен как функция-член с произвольным числом параметров. Параметры и возвращаемое значение могут иметь любые типы, допустимые для функций (см. разделы 7.2, 7.3 и 7.4). operator() вызывается путем применения списка аргументов к объекту того класса, в котором он определен. Мы рассмотрим, как он используется в одном из обобщенных алгоритмов, описанных в главе 12. В следующем примере обобщенный алгоритм transform() вызывается для применения определенной в absInt операции к каждому элементу вектора ivec, т.е. для замены элемента его абсолютным значением.

#include <vector>

#include <algoritm>

int main() {

int ia[] = { -0, 1, -1, -2, 3, 5, -5, 8 };

vector< int > ivec( ia, ia+8 );

// заменить каждый элемент его абсолютным значением

transform( ivec.begin(), ivec.end(), ivec.begin(), absInt() );

// ...


}

Первый и второй аргументы transform() ограничивают диапазон элементов, к которым применяется операция absInt. Третий указывает на начало вектора, где будет сохранен результат применения операции.

Четвертый аргумент – это временный объект класса absInt, создаваемый с помощью конструктора по умолчанию. Конкретизация обобщенного алгоритма transform(), вызываемого из main(), могла бы выглядеть так:

typedef vector< int >::iterator iter_type;

// конкретизация transform()

// операция absInt применяется к элементу вектора int

iter_type transform( iter_type iter, iter_type last,

iter_type result, absInt func )

{

while ( iter != last )

*result++ = func( *iter++ ); // вызывается absInt::operator()

return iter;


}

func – это объект класса, который предоставляет операцию absInt, заменяющую число типа int его абсолютным значением. Он используется для вызова перегруженного оператора operator() класса absInt. Этому оператору передается аргумент *iter, указывающий на тот элемент вектора, для которого мы хотим получить абсолютное значение.