Як ми вже знаємо з уроку про неявну конвертацію типів даних, мова C++ дозволяє конвертувати значення з одного типу даних в інший. Наприклад, перетворимо значення типу int в значення типу double:
1 2 |
int a = 7; double b = a; // значення типу int неявно конвертується в значення типу double |
Мова C++ за замовчуванням знає, як виконувати конвертацію вбудованих типів даних. Однак вона не знає, як виконувати конвертацію з користувацькими типами даних (наприклад, з класами). Саме тут вступає в гру перевантаження операцій конвертації типів даних. Розглянемо наступний клас:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Dollars { private: int m_dollars; public: Dollars(int dollars=0) { m_dollars = dollars; } int getDollars() { return m_dollars; } void setDollars(int dollars) { m_dollars = dollars; } }; |
Клас Dollars містить певну кількість доларів у вигляді цілого числа (змінна-член m_dollars
) і надає функції доступу для отримання і встановлення значення m_dollars
. У ньому також є конструктор для конвертації значень типу int в тип Dollars (при створенні об’єкту користувач передає в якості аргументу значення типу int, яке потім перетворюється в значення типу Dollars).
Якщо ми можемо конвертувати int в Dollars, то логічно було б, якби ми могли конвертувати і Dollars назад в int, чи не так? Іноді це може бути корисно.
У наступному прикладі ми використовуємо метод getDollars() для конвертації значення типу Dollars в тип int для його подальшого виводу через функцію printInt():
1 2 3 4 5 6 7 8 9 10 11 12 |
void printInt(int value) { std::cout << value; } int main() { Dollars dollars(9); printInt(dollars.getDollars()); // виведеться 9 return 0; } |
Погодьтеся, викликати кожного разу метод getDollars() не дуже зручно. Було б простіше перевантажити операцію конвертації значень типу Dollars в тип int. Робиться це наступним чином:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Dollars { private: int m_dollars; public: Dollars(int dollars=0) { m_dollars = dollars; } // Перевантаження операції конвертації значень типу Dollars в значення типу int operator int() { return m_dollars; } int getDollars() { return m_dollars; } void setDollars(int dollars) { m_dollars = dollars; } }; |
Тут є дві речі, на які слід звернути увагу:
В якості функції перевантаження використовується метод operator int()
. Зверніть увагу, між словом operator
і типом, в який ми хочемо виконати конвертацію (в даному випадку, тип int), знаходиться пробіл.
Функція перевантаження не має типу повернення. Мова C++ передбачає, що ви повертатимете коректний тип.
Тепер функція printInt() викликається простіше:
1 2 3 4 5 6 7 |
int main() { Dollars dollars(9); printInt(dollars); // виведеться 9 return 0; } |
Спочатку компілятор бачить (з визначення printInt()), що функція printInt() повинна приймати цілочисельний параметр. Потім він бачить, що змінна dollars
не є типу int. Він дивиться, чи надали ми спосіб конвертації значення типу Dollars в тип int. Так як це у нас є, то викликається operator int(), який повертає значення типу int, і це значення передається в printInt().
Тепер ми можемо явно конвертувати об’єкт класу Dollars в тип int:
1 2 |
Dollars dollars(9); int d = static_cast<int>(dollars); |
Ви можете перевантажувати операції перетворення будь-яких типів даних, включаючи ваші власні (користувацькі) типи даних!
Наприклад, ось клас Cents, в якому здійснене перевантаження операції перетворення значення типу Cents в значення типу Dollars:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Cents { private: int m_cents; public: Cents(int cents=0) { m_cents = cents; } // Виконуємо конвертацію Cents в Dollars operator Dollars() { return Dollars(m_cents / 100); } }; |
Таким чином ми можемо напряму конвертувати центи в долари:
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 44 45 |
#include <iostream> class Dollars { private: int m_dollars; public: Dollars(int dollars = 0) { m_dollars = dollars; } // Перевантаження операції конвертації значення типу Dollars в значення типу int operator int() { return m_dollars; } int getDollars() { return m_dollars; } void setDollars(int dollars) { m_dollars = dollars; } }; class Cents { private: int m_cents; public: Cents(int cents=0) { m_cents = cents; } // Виконуємо конвертацію Cents в Dollars operator Dollars() { return Dollars(m_cents / 100); } }; void printDollars(Dollars dollars) { std::cout << dollars; // dollars неявно конвертується в int тут } int main() { Cents cents(700); printDollars(cents); // cents неявно конвертується в Dollars тут return 0; } |
Результат виконання програми:
7
Все логічно: 700 центів = 7 доларів!