Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

14.4. Перевантаження оператора індексації масивів ([])

На додаток до традиційних операторів мова програмування C++ дає змогу перевантажувати і більш "екзотичні", наприклад, оператор індексації масивів ([]). У мові програмування C++ (з погляду механізму перевантаження) оператор "[]" вважається бінарним. Його можна перевантажувати тільки для класу і тільки з використанням функції-члена класу. Ось як виглядає загальний формат операторної функції-члена класу operator[]().

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

{

//...

}

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

Оператор "[]" перевантажується як бінарний оператор.

Припустимо, нехай визначено об'єкт A_ob, тоді вираз A_ob[-3] перетвориться в такий виклик операторної функції operator[]():

A_ob.operator[](3);

Іншими словами, значення виразу, що задається в операторі індексації, передається операторній функції operator[]() як безпосередньо заданий аргумент. При цьому покажчик this вказуватиме на об'єкт A_ob, тобто об'єкт, який генерує виклик цієї функції.

У наведеному нижче коді програми в класі aClass оголошується масив для зберігання трьох int-значень. Його конструктор ініціалізує кожного члена цього масиву. Перевантажена операторна функція operator[]()| повертає значення елемента, що задається його параметром.

Код програми 14.9. Демонстрація механізму перевантаження оператора індексації масиву "[]"

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

const int size = 3;

class aClass { // Оголошення класового типу

int aMas[size];

public:

aClass() { register int i; for(i=0; i<size; i++) aMas[i] = i;}

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

};

int main()

{

aClass A_ob;

cout << A_ob[2]; // Відображає число 2

getch(); return 0;

}

У цій програмі функція operator[]() повертає значення 1-го елемента масиву aMas. Таким чином, вираз A_ob[2] повертає число 2, яке відображається настановою cout. Ініціалізація масиву aMas за допомогою конструктора (у цій і наступній програмах) виконується тільки з ілюстративною метою.

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

Код програми 14.10. Демонстрація повернення посилання з операторної функції operator()[]

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

const int size = 3;

class aClass { // Оголошення класового типу

int aMas[size];

public:

aClass() { register int i; for(i=0; i<size; i++) aMas[i] = i;}

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

};

int main()

{

aClass A_ob;

cout << A_ob[2]; // Відображається число 2.

cout << " ";

A_ob[2] = 25; // Оператор "[]" знаходиться зліва від оператора присвоєння "=".

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

getch(); return 0;

}

У процесі виконання ця програма відображає на екрані такі результати:

2 25

Оскільки функція operator[]() тепер повертає посилання на елемент масиву, індексований параметром i, то оператор "[]" можна використовувати зліва від оператора присвоєння, що дасть змогу модифікувати будь-який елемент масиву1.

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

Код програми 14.11. Демонстрація прикладу організації безпечного масиву

#include <iostream> // Для потокового введення-виведення

#include <cstdlib> // Для використання бібліотечних функцій

using namespace std; // Використання стандартного простору імен

const int size = 3;

class aClass { // Оголошення класового типу

int aMas[size];

public:

aClass() { register int i; for(i=0; i<size; i++) aMas[i] = i;}

int &operator[](int i);

};

// Забезпечення контролю попадання в допустимий інтервал для класу aClass.

int &аClass::operator[](int i)

{

if(i<0 || i> size-1) {

cout << "\n Значення| індексу " << i

<< " виходить за межі масиву.\n";

exit(1);

}

return aMas[i];

}

int main()

{

aClass A_ob;

cout << A_ob[2]; // Відображається число 2.

cout << " ";

A_ob[2] = 25; // Оператор "[]" знаходиться в лівій частині.

cout << A_ob[2]; // Відображається число 25.

A_ob[3] = 44; // Генерується помилка часу виконання.

// оскільки значення 3 виходить за межі масиву.

getch(); return 0;

}

У процесі виконання ця програма виводить такі результати:

2 25

Значення індексу 3 виходить за межі масиву.

У процесі виконання настанови

A_ob[3] = 44;

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