Розглянемо унарні оператори плюс (+
), мінус (-
) і логічне НЕ (!
), які працюють з одним операндом. Так як вони застосовуються тільки до одного об’єкту, то їх перевантаження слід виконувати через методи класу.
Наприклад, перевантажимо унарний оператор мінус (-
) для класу Dollars:
1 2 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 |
#include <iostream> class Dollars { private: int m_dollars; public: Dollars(int dollars) { m_dollars = dollars; } // Виконуємо -Dollars через метод класу Dollars operator-() const; int getDollars() const { return m_dollars; } }; // Ця функція є методом класу! Dollars Dollars::operator-() const { return Dollars(-m_dollars); } int main() { const Dollars dollars1(7); std::cout << "My debt is " << (-dollars1).getDollars() << " dollars.\n"; return 0; } |
Примітка: Визначення методу можна записати і всередині класу. Тут ми визначили його поза тілом класу для кращої наочності прикладу.
Все досить-таки просто. Перевантаження від’ємного унарного оператора мінус (-
) здійснюється через метод класу, так як явні параметри в функції перевантаження відсутні (тільки неявний об’єкт, на який вказує прихований вказівник *this). Оператор -
повертає об’єкт Dollars з від’ємним значенням m_dollars
. Оскільки цей оператор не змінює об’єкт класу Dollars, то ми можемо (і повинні) зробити функцію перевантаження константною (щоб мати можливість використовувати цей оператор і з константними об’єктами класу Dollars).
Зверніть увагу, плутанини між від’ємним унарним оператором мінус (-
) і бінарним оператором мінус (-
) немає, так як вони мають різну кількість параметрів.
Ось ще один приклад: оператор !
є логічним оператором НЕ, який повертає true
, якщо результатом виразу є false
і повертає false
, якщо результатом виразу є true
. Зазвичай це застосовується до змінних типу bool, щоб перевірити, чи є вони true
чи ні:
1 2 3 4 |
if (!isHappy) std::cout << "I am not happy!\n"; else std::cout << "I am so happy!\n"; |
У мові С++ значення 0
означає false
, а будь-яке інше ненульове значення означає true
, тому, якщо логічний оператор !
застосовувати до цілочисельних значень, він повертатиме true
, якщо значенням змінної є 0
, в протилежному випадку — false
.
Отже, при роботі з класами, оператор !
повертатиме true
, якщо значенням об’єкта класу є false
, 0
або будь-яке інше значення, задане як дефолтне (за замовчуванням) при ініціалізації, в протилежному випадку оператор !
повертатиме false
.
У наступному прикладі ми розглянемо перевантаження унарного оператора мінус (−
) і оператора логічного НЕ (!
) для класу Something:
1 2 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 37 38 39 40 41 42 43 |
#include <iostream> class Something { private: double m_a, m_b, m_c; public: Something(double a = 0.0, double b = 0.0, double c = 0.0) : m_a(a), m_b(b), m_c(c) { } // Конвертуємо об'єкт класу Something у від'ємний Something operator- () const { return Something(-m_a, -m_b, -m_c); } // Повертаємо true, якщо використовуються значення за замовчуванням, в протилежному випадку - false bool operator! () const { return (m_a == 0.0 && m_b == 0.0 && m_c == 0.0); } double getA() { return m_a; } double getB() { return m_b; } double getC() { return m_c; } }; int main() { Something something; // використовуємо конструктор за замовчуванням зі значеннями 0.0, 0.0, 0.0 if (!something) std::cout << "Something is null.\n"; else std::cout << "Something is not null.\n"; return 0; } |
Тут перевантажений оператор НЕ (!
) повертає true
, якщо в Something використовуються значення за замовчуванням (0.0
, 0.0
, 0.0
).
Результат виконання програми:
Something is null.
Якщо ж задати будь-які ненульові значення для об’єкта класу Something:
1 |
Something something(23.11, 37.1, 20.12); |
То результатом буде:
Something is not null.
Тест
Реалізуйте перевантаження унарного оператора плюс (+
) для класу Something.
Відповідь
Є два рішення.
Рішення №1:
1 2 3 4 |
Something Something::operator+ () const { return Something(m_a, m_b, m_c); } |
Рішення №2:
1 2 3 4 |
Something Something::operator+ () const { return *this; } |
Це працює, тому що Something, який ми повертаємо, є поточним об’єктом.