Перевантаження оператору () виклику функції. Приклади
Зміст
- 1. Особливості перевантаження оператору ( ) виклику функції. Операторна функція operator()(). Загальна форма
- 2. Скільки параметрів може приймати операторна функція operator()(), яка перевантажує оператор виклику функції?
- 3. Приклади перевантаження оператору ( ) виклику функції
- 4. Приклад використання операторної функції operator()() яка використовується у поєднанні з іншою операторною функцією operator+()
- Зв’язані теми
Пошук на інших ресурсах:
1. Особливості перевантаження оператору () виклику функції. Операторна функція operator()(). Загальна форма
Оператор виклику функції може бути перевантажений. У цьому випадку у класі створюється операторна функція operator()(). Ця функція може приймати довільну кількість параметрів
Загальна форма реалізації операторної функції, що перевантажує оператор operator()() наступна.
Якщо у деякому класі з іменем ClassName перевантажена операторна функція operator()()
class ClassName { // ... return_type operator()(parameters) { // ... } };
то при виклику в іншому коді об’єкту з іменем obj класу ClassName
ClassName obj; obj(parameters);
цей виклик буде перетворено в наступний виклик операторної функції
obj.operator()(parameters);
тут
- ClassName – ім’я класу, в якому реалізована операторна функція operator()();
- return_type – тип, який повертає операторна функція operator()();
- parameters – параметри, які отримує операторна функція operator()();
- obj – екземпляр (об’єкт) класу ClassName.
⇑
2. Скільки параметрів може приймати операторна функція operator()(), яка перевантажує оператор виклику функції?
Операторна функція operator()() може приймати будь-яку кількість параметрів. Операторна функція operator()() може бути без параметрів.
⇑
3. Приклади перевантаження оператору () виклику функції
Приклад 1. Задано клас SqEqual, що містить усі дані та методи для розв‘язку квадратного рівняння.
У класі SqEqual реалізовано
- внутрішні приховані (private) дані a, b, c, x1, x2 для рішення задачі;
- конструктор класу;
- внутрішня прихована (private) функція Solution(), в якій реалізовано алгоритм розв’язку квадратного рівняння. Ця функція викликається з інших методів та операторних функцій класу;
- загальнодоступні (public) методи GetSolution() та GetSolutionP(), які викликають функцію Solution() для розв’язку квадратного рівняння. Ці методи можна викликати з екземпляру класу. Методи реалізовані з метою демонстрації передачі параметрів за посиланням та за покажчиком;
- дві перевантажені загальнодоступні операторні функції operator()(), які можна викликати для отримання розв’язку квадратного рівняння. Функції отримують різну кількість параметрів, тому вони сприймаються компілятором як різні функції. Функція operator()() з двома параметрами в якості коефіцієнтів рівняння використовує значення внутрішніх прихованих (private) змінних класу a, b, c. Функція operator()() з п’ятьма параметрами для розв’язку використовує вхідні параметри a, b, c.
Текст програми, що містить реалізацію класу SqEqual, створеної за шаблоном Console Application наступний
#include <iostream> using namespace std; // клас, що реалізує дані та методи розв'язку квадратного рівняння class SqEqual { private: // коефіцієнти квадратного рівняння double a; double b; double c; // корені - розв'язки double x1; double x2; // внутрішній метод розв'язку квадратного рівняння bool Solution(void) { double d; // дискримінант // чи взагалі є рівняння? if (a==0) return false; d = b*b-4*a*c; if (d>=0) { // є розв'язок рівняння x1 = (-b - sqrt(d)) / (2*a); x2 = (-b + sqrt(d)) / (2*a); } else return false; // рівняння не має розв'язку return true; // є розв'язок в змінних x1, x2 } public: // конструктор класу SqEqual(double a, double b, double c) { this->a = a; this->b = b; this->c = c; } // загальнодоступні методи розв'язку квадратного рівняння bool GetSolution(double& x1, double& x2) { if (Solution()) // викликати внутрішній метод розв'язку { x1 = this->x1; x2 = this->x2; return true; // є розв'язок } return false; // немає розв'язку } bool GetSolutionP(double* x1, double* x2) { if (Solution()) { *x1 = this->x1; *x2 = this->x2; return true; // є розв'язок } return false; // немає розв'язку } // операторна функція operator()(), що розв'язує квадратне рівняння // операторна функція отримує 5 параметрів // функція повертає true, якщо рівняння має розв'язок, // x1, x2 - розв'язок рівняння, передаються за покажчиком bool operator()(double a, double b, double c, double* x1, double* x2) { this->a = a; this->b = b; this->c = c; if (Solution()) { *x1 = this->x1; *x2 = this->x2; return true; } return false; } // варіант 2 - операторна функція отримує тільки 2 параметри, що є розв'язком // x1, x2 - передаються як посилання bool operator()(double& x1, double& x2) { // коефіцієнти a, b, c отримуються з поточного об'єкту if (Solution()) { x1 = this->x1; x2 = this->x2; return true; // є рішення } return false; // рівняння немає розв'язку } }; void main(void) { // перевантаження оператора () виклику функції double a = 2, b = -3, c = 1; SqEqual e(a, b, c); // створити екземпляр double x1, x2; bool f; // виклик операторної функції operator()() з двома параметрами f = e(x1,x2); if (f) { // якщо є рішення рівняння 2*x^2 - 3*x + 1 = 0, то вивести результат cout << a << "* x^2 + (" << b << ") * x + (" << c << ") = 0" << endl; cout << "x1 = " << x1 << endl; cout << "x2 = " << x2 << endl << endl; } // виклик операторної функції з 5 параметрами f = e(5, -7, 2, &x1, &x2); if (f) { // якщо є рішення рівняння, то вивести результат cout << "5 * x^2 - 7*x + 2 = 0" << endl; cout << "x1 = " << x1 << endl; cout << "x2 = " << x2 << endl << endl; } }
Як видно з вищенаведеного коду, у функції main() виклик операторної функції operator()() з двома параметрами наступний
f = e(x1, x2);
Якщо рівняння має розв’язок, то змінні x1 та x2 будуть мати відповідні значення. У цій операторній функції передача значень у змінні x1, x2 відбувається за посиланням.
Виклик операторної функції operator()() з п’ятьма параметрами наступний
f = e(5, -7, 2, &x1, &x2);
У цьому випадку у функцію передаються адреси змінних x1, x2. У функції доступ до змінних відбувається за покажчиком.
Результат виконання програми
2* x^2 + (-3) * x + (1) = 0 x1 = 0.5 x2 = 1 5 * x^2 - 7*x + 2 = 0 x1 = 0.4 x2 = 1
Приклад 2. Нехай задано клас Point, що реалізує точку на координатній площині.
У класі Point оголошуються:
- внутрішні приховані (private) змінні x, y;
- конструктор класу, який ініціалізує нульовими значеннями значення змінних x, y;
- методи доступу до внутрішніх змінних SetP(), GetX(), GetY();
- перевантажена операторна функція operator()() без параметрів. Ця функція повертає поточний об’єкт (екземпляр) класу;
- перевантажена операторна функція operator()() з двома параметрами. Ця функція повертає поточний екземпляр класу, значення внутрішніх змінних x, y якого рівні значенню відповідних параметрів _x, _y.
Реалізація класу Point наступна:
// клас, що реалізує точку class Point { private: int x, y; public: Point() { x = y = 0; } // методи доступу void SetP(int _x, int _y) { x = _x; y = _y; } int GetX() { return x; } int GetY() { return y; } // перевантаження операторної функції operator()() без параметрів Point operator()() { return *this; // повернути поточний об'єкт } // перевантаження операторної функції operator()() з двома параметрами Point operator()(int _x, int _y) { x = _x; y = _y; return *this; } };
Використання операторної функції operator()() класу Point в іншому методі може бути, наприклад, таким
// перевантаження оператора () виклику функції Point p1; // створити об'єкт int t; p1.SetP(3,5); // встановити значення Point p2; // новий об'єкт // виклик операторної функції без параметрів p2 = p1(); // перевірка t = p2.GetX(); // t = 3 t = p2.GetY(); // t = 5 // виклик операторної функції operator()() з двома параметрами p2 = p1(7,8); // перевірка t = p2.GetX(); // t = 7 t = p2.GetY(); // t = 8
Як видно з вищенаведеного прикладу, операторна функція operator()() може мати декілька реалізацій в класі. Ці реалізації повинні відрізнятися кількістю або типами параметрів, які передаються в операторну функцію.
⇑
4. Приклад використання операторної функції operator()() яка використовується у поєднанні з іншою операторною функцією operator+()
У прикладі оголошується клас Complex, в якому перевантажуються:
- оператор виклику функції ( );
- оператор додавання +, який здійснює додавання комплексних чисел.
У класі Complex реалізовано наступні елементи:
- внутрішні приховані (private) змінні real та imag. Ці змінні визначають дійсну та уявну частину комплексного числа;
- два конструктори;
- методи GetI() та GetR() для читання значень внутрішніх змінних real та imag;
- операторна функція operator+(), яка переваантажує оператор +. Функція сумує два екземпляри (об’єкти) класу Complex;
- операторна функція operator()(), яка перевантажує оператор виклику функції (). Функція створює екземпляр класу Complex на основі вхідних параметрів.
Текст програми типу Console Application, що демонструє реалізацію класу Complex наступний
#include <iostream> using namespace std; // клас, що реалізує комплексне число class Complex { private: double real; // дійсна частина комплексного числа double imag; // уявна частина public: // конструктори Complex() { real = imag = 0; } Complex(double real, double imag) { this->real = real; this->imag = imag; } // методи доступу double GetI() { return imag; } double GetR() { return real; } // перевантажений оператор додавання + Complex operator+(Complex c) { // додавання комплексних чисел return Complex(real + c.real, imag + c.imag); } // перевантажений оператор виклику функції Complex operator()(double real, double imag) { this->real = real; this->imag = imag; return *this; } }; void main() { Complex c1(3, 4); Complex c2; Complex c3; double r, i; // виклик операторних функцій operator+() та operator()() c3 = c1 + c2(5, 6); // c3 = c1.operator+(c2.operator(5,6)) // перевірка r = c3.GetR(); // r = 3 + 5 = 8 i = c3.GetI(); // i = 4 + 6 = 10 cout << "r = " << r << endl; cout << "i = " << i; }
Результат виконання програми
r = 8 i = 10
⇑
Зв’язані теми
- Перевантаження операторів у C++. Операторна функція. Ключове слово operator. Перевантаження арифметичних операторів +, –, *, /. Приклади реалізації вбудованих операторних функцій
- “Дружні” операторні функції: відмінності, реалізація особливості застосування. Перевантаження операторів +, –, *, / з допомогою “дружніх” операторних функцій
- Перевантаження оператора індексування елементів масиву [ ]
⇑