ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 8) онлайн
Операция индексации массива ([])
Операция индексации, которая обычно используется для доступа к элементам массива, может быть перегружена. Это полезно в том случае, если вы хотите изменить способ работы C++ с массивами. Например, если вам понадобится создать «безопасный массив», в котором заложена автоматическая проверка ис-
пользуемого для доступа к массиву индекса элемента. Она будет проверять, на- ходитесь ли вы в границах массива. (Вы можете также использовать класс vector, описанный в главе 15 «Стандартная библиотека шаблонов (STL)».)
Для демонстрации перегрузки операции индексации массива мы должны вернуться к другой теме, с которой мы уже встречались в главе 5, — возвращению значений из функции по ссылке. Перегруженная операция индексации должна возвращать свои значения по ссылке. Чтобы показать, почему это так, мы рас- смотрим три программы, которые реализуют «безопасный» массив, каждая при этом использует свой подход для вставки и считывания элементов массива:
два отдельных метода put() и get();
метод access(), использующий возвращение по ссылке;
перегруженная операция [ ], использующая возвращение по ссылке.
Все три программы используют класс safearray, в котором определен массив, состоящий из 100 элементов типа int. И все три проверяют, находится ли эле- мент, к которому мы хотим получить доступ, в границах массива. Функция main() каждой из программ заполняет массив значениями (каждое из которых равно значению индекса массива, умноженному на 10) и затем выводит их все, чтобы показать, что пользователь сделал все правильно.
Два отдельных метода put() и get()
В первой программе мы используем для доступа к элементам массива два мето- да: putel() для вставки элемента в массив и getel() для получения значения нуж- ного нам элемента. Оба метода проверяют, чтобы значение индекса массива вхо- дило в рамки границ массива. То есть оно не должно быть меньше 0 и больше размера массива (минус 1). Приведем листинг программы ARROVER1.
// arrover1.cpp
// демонстрация создания безопасного массива, проверяющего
// свои индексы при использовании
// используются отдельные функции для установки и получения значения
#include <iostream>
using namespace std;
#include <process.h> // для функции exit
const int LIMIT = 100; // размер массива
///////////////////////////////////////////////////////////
class safearray
{
private:
int arr [ LIMIT ];
public:
// установка значения элемента массива
void putel ( int n, int elvalue )
{
if ( n < 0 || n >= LIMIT )
{ cout << "\nОшибочный индекс!"; exit ( 1 ); }
arr [ n ] = elvalue;
}
// получение значения элемента массива
int getel ( int n ) const
{
if ( n < 0 || n >= LIMIT )
{ cout << "\nОшибочный индекс!"; exit ( 1 ); }
return arr [ n ];
}
};
///////////////////////////////////////////////////////////
int main ( )
{
safearray sa1;
// задаем значения элементов
for ( int j = 0; j < LIMIT; j++ )
sa1.putel ( j, j * 10 );
// показываем элементы
for ( j = 0; j < LIMIT; j++ )
{
int temp = sa1.getel ( j );
cout << "Элемент " << j << " равен " << temp << endl;
}
return 0;
}
Данные помещаются в массив с помощью метода putel() и выводятся на дис- плей с помощью метода getel(). Безопасность массива реализована с помощью вывода сообщения об ошибке при попытке использования индекса, не входяще- го в границы массива. Однако этот формат несколько груб.
Метод access (), использующий возвращение по ссылке
Как оказывается, мы можем использовать один метод для вставки и вывода эле- ментов массива. Секрет этого метода в использовании возвращения значения по ссылке. Это означает, что мы можем записать функцию с левой стороны знака равно, при этом переменной, стоящей справа, будет присвоено значение, возвра- щаемое функцией, как показано в главе 5. Приведем листинг программы ARROVER2.
// arrover2.cpp
// демонстрация создания безопасного массива, проверяющего
// свои индексы при использовании
// используется общая функция для установки и получения значения
#include <iostream>
using namespace std;
#include <process.h> // для функции exit
const int LIMIT = 100; // размер массива
///////////////////////////////////////////////////////////
class safearray
{
private:
int arr [ LIMIT ];
public:
// обратите внимание, что функция возвращает ссылку!
int& access ( int n )
{
if ( n < 0 || n >= LIMIT )
{ cout << "\nОшибочный индекс!"; exit ( 1 ); }
return arr [ n ];
}
};
///////////////////////////////////////////////////////////
int main ( )
{
safearray sa1;
// задаем значения элементов
for ( int j = 0; j < LIMIT; j++ )
sa1.access ( j ) = j * 10; // используем функцию слева от знака =
// показываем элементы
for ( j = 0; j < LIMIT; j++ )
{
int temp = sa1.access ( j ); // используем функцию справа от знака =
cout << "Элемент " << j << " равен " << temp << endl;
}
return 0;
}
Строка sal.access ( j ) = j * 10;
означает, что значение j*10 будет помещено в элемент массива arr[j], ссылка на который возвращается методом.
Это использование одного метода для ввода и вывода элементов массива в общем случае немного более удобно, чем использование отдельных методов, на одно имя меньше. Но существует еще лучший способ, вовсе без имен.
Перегруженная операция [], использующая возвращение по ссылке
Мы перегрузим операцию индексации [ ] в классе safearray для использования стандартной записи C++ для доступа к элементам массива. Однако, так как эта операция обычно используется слева от знака равно, наша перегруженная функ- ция должна возвращать свое значение по ссылке, как показано в предыдущей программе. Листинг программы ARROVER3:
// arrover3.cpp
// демонстрация создания безопасного массива, проверяющего
// свои индексы при использовании
// используется перегрузка операции [ ]
#include <iostream>
using namespace std;
#include <process.h> // для функции exit
const int LIMIT = 100; // размер массива
///////////////////////////////////////////////////////////
class safearray
{
private:
int arr [ LIMIT ];
public:
// обратите внимание, что функция возвращает ссылку!
int& operator[ ] ( int n )
{
if ( n < 0 || n >= LIMIT )
{ cout << "\nОшибочный индекс!"; exit ( 1 ); }
return arr [ n ];
}
};
///////////////////////////////////////////////////////////
int main ( )
{
safearray sa1;
// задаем значения элементов
for ( int j = 0; j < LIMIT; j++ )
sa1[ j ] = j * 10; // используем функцию слева от знака =
// показываем элементы
for ( j = 0; j < LIMIT; j++ )
{
int temp = sa1 [ j ]; // используем функцию справа от знака =
cout << "Элемент " << j << " равен " << temp << endl;
}
return 0;
}
В этой программе мы можем использовать обычную запись операции индек- сации массива
sa1[ j ] = j * 10; и
int temp = sa1 [ j ];
для ввода и вывода элементов массива.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
