Урок №145. Перевантаження операторів інкременту і декременту

  Юрій  | 

  Оновл. 17 Лют 2021  | 

 113

Перевантаження операторів інкременту (++) і декременту (−−) досить-таки просте, але з одним маленьким нюансом. Є дві версії операторів інкременту і декременту: версія префікс (наприклад, ++x, --y) і версія постфікс (наприклад, x++, y--).

Оскільки оператори інкременту і декременту є унарними і змінюють свої операнди, то перевантаження слід виконувати через методи класу.

Перевантаження операторів інкременту і декременту версії префікс

Перевантаження операторів інкременту і декременту версії префікс аналогічне перевантаженню будь-яких інших унарних операторів:

Тут клас Number містить число від 0 до 8. Ми перевантажили оператори інкременту/декременту таким чином, щоб вони збільшували/зменшували m_number відповідно до заданого діапазону (якщо виконується інкремент і m_number дорівнює 8, то скидаємо значення m_number на 0; якщо виконується декремент і m_number дорівнює 0, то присвоюємо значення 8 змінній m_number).

Результат виконання програми:

78087

Зверніть увагу, ми повертаємо прихований вказівник *this в функціях перевантаження операторів (тобто поточний об’єкт класу Number). Таким чином ми можемо зв’язати виконання декількох операторів в один «ланцюжок».

Перевантаження операторів інкременту і декременту версії постфікс

Зазвичай перевантаження функцій здійснюється, якщо вони мають одне і те ж ім’я, але різну кількість і типи параметрів. Розглянемо випадок з операторами інкременту/декременту версій префікс/постфікс. Обидва мають одне і те ж ім’я (наприклад, operator++), унарні і приймають один параметр одного і того ж типу даних. Як же тоді їх розрізнити при перевантаженні?

Справа в тому, що мова C++ використовує фіктивну змінну (або «фіктивний параметр») для операторів версії постфікс. Цей фіктивний цілочисельний параметр використовується тільки з однією метою: відрізнити версію постфікс операторів інкременту/декременту від версії префікс. Виконаємо перевантаження операторів інкременту/декременту версії префікс і постфікс в одному класі:

Результат виконання програми:

6778776

Тут є декілька цікавих моментів:

   По-перше, ми відокремили версію постфікс від версії префікс використанням цілочисельного фіктивного параметра у версії постфікс.

   По-друге, оскільки фіктивний параметр не використовується в реалізації самого перевантаження, то ми навіть не надаємо йому ім’я. Таким чином, компілятор розглядатиме цю змінну, як просту заглушку (заповнювач місця), і навіть не попереджатиме нас про те, що ми оголосили змінну, але ніколи її не використали.

   По-третє, оператори версій префікс і постфікс виконують одне й те ж завдання: обидва збільшують/зменшують значення змінної об’єкта. Різниця між ними тільки в значенні, яке вони повертають.

Розглянемо останній пункт детально. Оператори версії префікс повертають об’єкт після того, як він був збільшений або зменшений. У версії постфікс нам потрібно повернути об’єкт до того, як він буде збільшений або зменшений. І тут конфуз! Якщо ми збільшуємо або зменшуємо об’єкт, то ми не можемо повернути його до виконання інкременту/декременту, так як операція збільшення/зменшення вже відбулася. З іншого боку, якщо ми повертаємо об’єкт до виконання інкременту/декременту, то сама операція збільшення/зменшення об’єкта не виконається.

Рішенням є використання тимчасового об’єкта з поточним значенням змінної-члена. Тоді можна буде збільшити/зменшити вихідний об’єкт, а тимчасовий об’єкт повернути назад в caller. Таким чином, caller отримає копію об’єкта до того, як фактичний об’єкт буде збільшений або зменшений, і сама операція інкременту/декременту виконається успішно.

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

Нарешті, ми реалізували перевантаження операторів версії постфікс через вже перевантажені оператори версії префікс. Таким чином, ми зменшили дублювання коду і спростили внесення змін до наш класу в майбутньому (тобто спростили підтримку коду).

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (1 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *