Перевантаження Операторів
Перевантаження операторів — це потужна можливість у мовах об'єктно-орієнтованого програмування, яка дозволяє перевизначати поведінку операторів для користувацьких classes
. Завдяки перевантаженню операторів можна створювати власні реалізації операцій для об'єктів вашого class
, що забезпечує більш інтуїтивний та виразний код.
Синтаксис перевантаження операторів
Перевантаження досягається шляхом визначення спеціальних функцій-членів або дружніх функцій, які реалізують необхідну поведінку для оператора. Синтаксис перевантаження операторів залежить від оператора, який ви хочете перевантажити. Загальний вигляд виглядає так:
overloading.h
1return_type operator operator_symbol(parameters);
Синтаксис, а точніше, кількість параметрів і тип, що повертається, також залежать від того, чи перевантажуєте ви оператори як функції-члени або як дружні функції.
Member.h
Friend.h
123456class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };
Таблиця операторів, які можна перевантажити
Нижче наведено таблицю всіх операторів, які можна перевантажити. Однак важливо зазначити, що хоча перевантаження цих операторів можливе, зовсім не обов'язково перевантажувати всі з них для ваших classes
.
Перевантаження операторів вставки у потік
Щоб перевантажити оператори <<
та >>
для class
, зазвичай визначають функцію-друга або метод-член, який приймає потік виводу (std::ostream&
) або потік вводу (std::istream&
) як лівий операнд і об'єкт вашого class
як правий операнд. Ця функція форматує дані об'єкта та передає їх у потік або з потоку.
Point.h
123456789101112131415class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }
Перевантаження операторів вставки у потік, таких як <<
, дозволяє визначити власну поведінку виводу для об'єктів ваших classes
при передачі їх у потік виводу, наприклад, у std::cout
. Ця можливість особливо корисна для підвищення читабельності та зручності використання вашого коду при роботі з власними типами даних.
Перевантаження оператора <<
для потоку виводу є більш поширеним, ніж перевантаження оператора >>
для потоку вводу, оскільки операції вводу з >>
можуть бути більш схильними до помилок.
Перевантаження арифметичних операторів
Можна перевантажувати й інші арифметичні оператори (-
, *
, /
, %
) аналогічним чином для виконання користувацьких операцій з вашими власними типами.
main.cpp
12345678910111213141516171819202122#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Оператор перевантажується як метод-член Point
class
. Він приймає інший об'єкт типу Point
як параметр і повертає новий об'єкт типу Point
, який представляє суму двох точок. Оператор +
можна замінити на -
, *
, /
або %
з відповідними змінами в логіці реалізації.
Інкремент і декремент
Як префіксний, так і постфіксний інкремент і декремент (++
та --
) можна перевантажити для користувацьких classes
. Почнемо з префіксної версії:
main.cpp
123456789101112131415161718192021222324#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Оператор декременту перевантажується аналогічно оператору інкременту, використовуючи оператор --
та операцію віднімання.
Як бачите, перевантаження префіксних операторів інкременту та декременту є простим. Однак із постфіксними версіями виникають складнощі. Зверніть увагу, що існує різниця в порядку виконання між префіксними та постфіксними операціями.
Під час перевантаження постфіксних операторів інкременту та декременту також необхідно реалізувати особливість порядку виконання. Це виглядатиме приблизно так:
main.cpp
1234567891011121314151617181920212223242526#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Цілий параметр передається без імені лише для того, щоб повідомити компілятору, що перевантажується оператор постфіксного інкременту. Це необхідно, оскільки оголошення для префіксного та постфіксного операторів інакше ідентичні.
У реалізації оператора постфіксного інкременту початкове значення об'єкта зберігається у тимчасовій змінній (temp
). Поточний об'єкт потім інкрементується, але оператор повертає значення, збережене у temp
. Це означає, що змінна інкрементується, але зміна набуває чинності лише у наступному виразі, оскільки оператор повертає початкове значення.
Дякуємо за ваш відгук!
Запитати АІ
Запитати АІ
Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат
Awesome!
Completion rate improved to 3.13
Перевантаження Операторів
Свайпніть щоб показати меню
Перевантаження операторів — це потужна можливість у мовах об'єктно-орієнтованого програмування, яка дозволяє перевизначати поведінку операторів для користувацьких classes
. Завдяки перевантаженню операторів можна створювати власні реалізації операцій для об'єктів вашого class
, що забезпечує більш інтуїтивний та виразний код.
Синтаксис перевантаження операторів
Перевантаження досягається шляхом визначення спеціальних функцій-членів або дружніх функцій, які реалізують необхідну поведінку для оператора. Синтаксис перевантаження операторів залежить від оператора, який ви хочете перевантажити. Загальний вигляд виглядає так:
overloading.h
1return_type operator operator_symbol(parameters);
Синтаксис, а точніше, кількість параметрів і тип, що повертається, також залежать від того, чи перевантажуєте ви оператори як функції-члени або як дружні функції.
Member.h
Friend.h
123456class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };
Таблиця операторів, які можна перевантажити
Нижче наведено таблицю всіх операторів, які можна перевантажити. Однак важливо зазначити, що хоча перевантаження цих операторів можливе, зовсім не обов'язково перевантажувати всі з них для ваших classes
.
Перевантаження операторів вставки у потік
Щоб перевантажити оператори <<
та >>
для class
, зазвичай визначають функцію-друга або метод-член, який приймає потік виводу (std::ostream&
) або потік вводу (std::istream&
) як лівий операнд і об'єкт вашого class
як правий операнд. Ця функція форматує дані об'єкта та передає їх у потік або з потоку.
Point.h
123456789101112131415class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }
Перевантаження операторів вставки у потік, таких як <<
, дозволяє визначити власну поведінку виводу для об'єктів ваших classes
при передачі їх у потік виводу, наприклад, у std::cout
. Ця можливість особливо корисна для підвищення читабельності та зручності використання вашого коду при роботі з власними типами даних.
Перевантаження оператора <<
для потоку виводу є більш поширеним, ніж перевантаження оператора >>
для потоку вводу, оскільки операції вводу з >>
можуть бути більш схильними до помилок.
Перевантаження арифметичних операторів
Можна перевантажувати й інші арифметичні оператори (-
, *
, /
, %
) аналогічним чином для виконання користувацьких операцій з вашими власними типами.
main.cpp
12345678910111213141516171819202122#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Оператор перевантажується як метод-член Point
class
. Він приймає інший об'єкт типу Point
як параметр і повертає новий об'єкт типу Point
, який представляє суму двох точок. Оператор +
можна замінити на -
, *
, /
або %
з відповідними змінами в логіці реалізації.
Інкремент і декремент
Як префіксний, так і постфіксний інкремент і декремент (++
та --
) можна перевантажити для користувацьких classes
. Почнемо з префіксної версії:
main.cpp
123456789101112131415161718192021222324#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Оператор декременту перевантажується аналогічно оператору інкременту, використовуючи оператор --
та операцію віднімання.
Як бачите, перевантаження префіксних операторів інкременту та декременту є простим. Однак із постфіксними версіями виникають складнощі. Зверніть увагу, що існує різниця в порядку виконання між префіксними та постфіксними операціями.
Під час перевантаження постфіксних операторів інкременту та декременту також необхідно реалізувати особливість порядку виконання. Це виглядатиме приблизно так:
main.cpp
1234567891011121314151617181920212223242526#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Цілий параметр передається без імені лише для того, щоб повідомити компілятору, що перевантажується оператор постфіксного інкременту. Це необхідно, оскільки оголошення для префіксного та постфіксного операторів інакше ідентичні.
У реалізації оператора постфіксного інкременту початкове значення об'єкта зберігається у тимчасовій змінній (temp
). Поточний об'єкт потім інкрементується, але оператор повертає значення, збережене у temp
. Це означає, що змінна інкрементується, але зміна набуває чинності лише у наступному виразі, оскільки оператор повертає початкове значення.
Дякуємо за ваш відгук!