Выбрать главу

тип имя_класса::operator[](int индекс)

{

 // ...

}

Оператор "[]" перегружается как бинарный оператор.

Формально параметр индекс необязательно должен иметь тип int, но операторные функции operator[]() обычно используются для обеспечения индексации массивов, поэтому в общем случае в качестве аргумента этой функции передается целочисленное значение.

Предположим, у нас определен объект ob, тогда выражение

ob[3]

преобразуется в следующий вызов операторной функции operator[]():

ob.operator[](3)

Другими словами, значение выражения, заданного в операторе индексации, передается операторной функции operator[]() в качестве явно заданного аргумента. При этом указатель this будет указывать на объект ob, т.е. объект, который генерирует вызов этой функции.

В следующей программе в классе atype объявляется массив для хранения трех int-значений. Его конструктор инициализирует каждый член этого массива. Перегруженная операторная функция operator[]() возвращает значение элемента, заданного его параметром.

// Перегрузка оператора индексации массивов

#include <iostream>

using namespace std;

const int SIZE = 3;

class atype {

  int a[SIZE];

 public:

  atype() {

   register int i;

   for(i=0; i<SIZE; i++) a[i] = i;

  }

  int operator[](int i) {return a[i];}

};

int main()

{

 atype ob;

 cout << ob[2]; // отображает число 2

 return 0;

}

Здесь функция operator[]() возвращает значение i-го элемента массива a. Таким образом, выражение ob[2] возвращает число 2, которое отображается инструкцией cout. Инициализация массива a с помощью конструктора (в этой и следующей программах) выполняется лишь в иллюстративных целях.

Можно разработать операторную функцию operator[]() так, чтобы оператор "[]" можно было использовать как слева, так и справа от оператора присваивания. Для этого достаточно указать, что значение, возвращаемое операторной функцией operator[](), является ссылкой. Эта возможность демонстрируется в следующей программе.

// Возврат ссылки из операторной функции operator()[].

#include <iostream>

using namespace std;

const int SIZE = 3;

class atype {

  int a[SIZE];

 public:

  atype() {

   register int i;

   for(i=0; i<SIZE; i++) a[i] = i;

  }

  int &operator[](int i) {return a[i];}

};

int main()

{

 atype ob;

 cout << ob[2]; // Отображается число 2.

 cout <<" ";

 ob[2] = 25; // Оператор "[]" стоит слева от оператора "=".

 cout << ob[2]; // Теперь отображается число 25.

 return 0;

}

При выполнении эта программа генерирует такие результаты.

2 25

Поскольку функция operator[]() теперь возвращает ссылку на элемент массива, индексируемый параметром i, оператор "[]" можно использовать слева от оператора присваивания, что позволит модифицировать любой элемент массива. (Конечно же, его по-прежнему можно использовать и справа от оператора присваивания.)

Одно из достоинств перегрузки оператора "[]" состоит в том, что с его помощью мы можем обеспечить средство реализации безопасной индексации массивов. Как вы знаете, в C++ возможен выход за границы массива во время выполнения программы без Соответствующего уведомления (т.е. без генерирования сообщения о динамической ошибке). Но если создать класс, который содержит массив, и разрешить доступ к этому массиву только через перегруженный оператор индексации "[]", то возможен перехват индекса, значение которого вышло за дозволенные пределы. Например, следующая программа (в основу которой положен код предыдущей) оснащена средством контроля попадания в допустимый интервал.