Перевантаження бінарних операторів. Перевантаження операторів +, –, *, /, %. Вкладення довільної логіки при перевантаженні
Перед вивченням даної теми рекомендується ознайомитись з наступною темою:
Зміст
- 1. Особливості перевантаження бінарних операторів
- 2. Перевантаження бінарних операторів +, –, *, /. Приклад
- 3. Особливості перевантаження операторів +=, -=, *=, /=, %=
- 4. Приклад перевантаження оператора %. Визначення середнього арифметичного двох масивів. Програмування довільної логіки при перевантаженні операторів
- Споріднені теми
Пошук на інших ресурсах:
1. Особливості перевантаження бінарних операторів
У мові C# допускається перевантажувати наступні бінарні оператори:
- + – додавання (a + b);
- – – віднімання (a – b);
- * – множення (a * b);
- / – ділення (a / b);
- % – оператор взяття остачі від ділення. Може бути перевантажений на власний розсуд;
- & – побітове логічне “І”;
- | – побітове логічне “АБО”;
- ^ – побітове додавання по модулю 2;
- <, > – оператори порівняння (менше, більше). У класі ці оператори обов’язково перевантажуються парою (обидва);
- <=, >= – оператори порівняння (менше або рівне, більше або рівне). Ці оператори перевантажуються парою;
- ==, != – оператори порівняння (дорівнює, не дорівнює). Перевантажуються парою в класі.
При перевантаженні бінарних операторів створюється статичний метод, який отримує 2 параметри. Тип цих параметрів є типом класу, в якому реалізується метод, що перевантажує оператор.
У найбільш загальному випадку перевантаження бінарного оператора в класі з іменем ClassName має вигляд:
class ClassName { public static ClassName operator op(ClassName obj1, ClassName obj2) { // Дії, які потрібно виконати при виклику obj1 op obj2 // ... } }
тут
- op – один з стандартних бінарних операторів, які можна перевантажувати (+, –, ==, > і т.д.);
- obj1 – екземпляр, що знаходиться зліва від оператора op;
- obj2 – екземпляр, що знаходиться справа від оператора op.
Після перевантаження, екземпляри obj1 та obj2 можна поєднувати оператором op у більш наочному вигляді
obj1 op obj2
Наприклад, якщо перевантажити оператор +, то виклик відповідного методу буде
obj1 + obj2
⇑
2. Перевантаження бінарних операторів +, –, *, /. Приклад
Задано клас Complex, що визначає комплексне число. У класі міститься мінімально-можливий набір методів та властивостей для повноцінного функціонування.
У класі Complex перевизначено оператори +, –, *, / які реалізують відповідно додавання, віднімання, множення та ділення двох комплексних чисел.
using System; namespace ConsoleApp6 { class Complex { // Внутрішні поля класу private double re, im; // Конструктор public Complex(double re, double im) { this.re = re; this.im = im; } // Властивості доступу до внутрішніх полів public double Re { get { return re; } set { re = value; } } public double Im { get { return im; } set { im = value; } } // Операторний метод, що перевантажує бінарний оператор '+', // реалізує додавання комплексних чисел public static Complex operator+(Complex cm1, Complex cm2) { return new Complex(cm1.re + cm2.re, cm1.im + cm2.im); } // Операторний метод, що перевантажує бінарний оператор '-', // реалізує віднімання комплексних чисел public static Complex operator-(Complex cm1, Complex cm2) { return new Complex(cm1.re - cm2.re, cm1.im - cm2.im); } // Метод, що перевантажує оператор '*' // реалізує множення комплексних чисел public static Complex operator*(Complex cm1, Complex cm2) { return new Complex(cm1.re * cm2.re - cm1.im * cm2.im, cm1.re * cm2.im + cm1.im * cm2.re); } // Перевантаження оператора '/' - ділення комплексних чисел public static Complex operator/(Complex cm1, Complex cm2) { double denom = cm2.re * cm2.re + cm2.im * cm2.im; return new Complex((cm1.re * cm2.re + cm1.im * cm2.im) / denom, (cm1.im * cm2.re - cm1.re * cm2.im) / denom); } // Метод, що виводить стан поточного екземпляру public void Print(string msg) { Console.Write(msg + " => "); Console.Write(re); if (im >= 0) Console.Write("+"); Console.WriteLine(im.ToString() + "*j"); } } internal class Program { static void Main(string[] args) { // 1. Створити 2 об'єкти типу Complex Complex cm1 = new Complex(3, 5); Complex cm2 = new Complex(2, -4); // 2. Вивести об'єкти cm1.Print("cm1"); cm2.Print("cm2"); // 3. Додати об'єкти Complex cm3; cm3 = cm1 + cm2; // викликається метод, що перевантажує оператор '+' cm3.Print("cm1 + cm2"); // 4. Відняти - виклик методу Complex.operator-() (cm1 - cm2).Print("cm1-cm2"); // 5. Помножити cm3 = cm1 * cm2; cm3.Print("cm1 * cm2"); // 6. Поділити cm3 = cm1 / cm2; cm3.Print("cm1 / cm2"); // 7. Використання операторів +=, -=, *=, /= Complex cm4 = new Complex(1, 1); cm4 += cm1; // => cm4 = cm4 + cm1; cm4.Print("cm4"); Complex cm5 = new Complex(2, 3); cm5 *= cm2; // => cm5 = cm5 * cm2 cm5.Print("cm5"); Console.ReadKey(); } } }
Результат
cm1 => 3+5*j cm2 => 2-4*j cm1 + cm2 => 5+1*j cm1-cm2 => 1+9*j cm1 * cm2 => 26-2*j cm1 / cm2 => -0.7+1.1*j cm4 => 4+6*j cm5 => 16-2*j
⇑
3. Особливості перевантаження операторів +=, -=, *=, /=, %=
Скорочені оператори присвоєння +=, -=, *=, /=, %= та інші подібні вважаються перевантаженими, як тільки перевантажені відповідні їм оператори +, –, *, /, % та інші.
На прикладі класу Point перевантажуються оператори + та –. Потім демонструється виклик відповідних операторів +=, –= для екземплярів класу Point.
Перевантажені оператори + та – виконують додавання та віднімання координат точок.
using System; namespace ConsoleApp6 { // Клас, що описує точку на координатній площині class Point { // Внутрішні змінні private int x, y; // Конструктор public Point(int x, int y) { this.x = x; this.y = y; } // Властивості доступу до координат точок public int X { get { return x; } } public int Y { get { return y; } } // Метод, що виводить поточні значення x, y public void Print(string msg) { Console.WriteLine(msg + " => " + "( " + x + "; " + y + ")"); } // Перевантажені оператори '+' та '-' public static Point operator+(Point p1, Point p2) { return new Point(p1.x + p2.x, p1.y + p2.y); } public static Point operator-(Point p1, Point p2) { return new Point(p1.x - p2.x, p1.y - p2.y); } } internal class Program { static void Main(string[] args) { // 1. Створити 2 екземпляри класу Point Point pt1 = new Point(3, 8); Point pt2 = new Point(4, 9); // 2. Використати оператор += для обчислення суми точок pt1 та pt2 pt1 += pt2; // => pt1 = pt1 + pt2; - виконується: pt1 = Point.operator+(pt1, pt2) pt1.Print("pt1"); // 3. Викликати оператор -= для обчислення різниці pt2 = pt2 - pt1; pt2 -= pt1; // pt2 = Point.operator(pt2, pt1); pt2.Print("pt2"); Console.ReadKey(); } } }
Після перевантаження операторів + та – у класі Point у функції main() викликаються відповідні оператори += та -= в рядках
pt1 += pt2; pt2 -= pt1;
Після виконання програма видає наступний результат
pt1 => ( 7; 17) pt2 => ( -3; -8)
⇑
4. Приклад перевантаження оператора %. Визначення середнього арифметичного двох масивів. Програмування довільної логіки при перевантаженні операторів
У методи, що перевантажують оператори можна вкладати код, що реалізує будь-які дії. Не обов’язково код перевантажуваного методу повинен відповідати призначенню оператора, який цей метод перевантажує.
Оператор % визначає остачу від ділення цілочисельних значень. Однак, у нашому випадку реалізована друга логіка. Визначається середнє арифметичне двох операндів, які є масивами типу ArrayDouble. Цей приклад носить демонстраційний характер і показує як по різному можна програмувати логіку методів, що перевизначають оператори.
Слід звернути увагу, що операторний метод operator%() повертає тип double а не ArrayDouble.
using System; namespace ConsoleApp6 { // Масив чисел з плаваючою комою class ArrayDouble { private double[] AD; // Конструктор public ArrayDouble(double[] _AD) { // Копіювання AD = _AD AD = new double[_AD.Length]; for (int i = 0; i < AD.Length; i++) AD[i] = _AD[i]; } // Метод, що виводить масив AD public void Print(string msg) { Console.Write(msg + " => "); for (int i = 0; i < AD.Length; i++) Console.Write(AD[i] + " "); Console.WriteLine(); } // Перевантаження оператора %. // Визначення середнього арифметичного двох масивів-операндів. // Звернути увагу: метод повертає double а не ArrayDouble public static double operator%(ArrayDouble AD1, ArrayDouble AD2) { // 1. Обчислити суму елементів масивів double res = 0; for (int i = 0; i < AD1.AD.Length; i++) res += AD1.AD[i]; for (int i = 0; i < AD2.AD.Length; i++) res += AD2.AD[i]; // 2. Повернути середнє арифметичне return res / (AD1.AD.Length + AD2.AD.Length); } } internal class Program { static void Main(string[] args) { // 1. Створити 2 масиви типу double[] double[] A1 = { 2.4, 3.1, 0.8, -2.2, 0.9, 11.6 }; double[] A2 = { 3.8, 11.7, -4.4, 0.8 }; // 2. На основі масивів створити 2 екземпляри ArrayDouble AD1 = new ArrayDouble(A1); ArrayDouble AD2 = new ArrayDouble(A2); // 3. Вивести масиви для контролю AD1.Print("AD1"); AD2.Print("AD2"); // 4. Використати перевантажений оператор % для // обчислення середнього арифметичного double average = AD1 % AD2; Console.WriteLine("AD1 % AD2 = {0:f3}", average); Console.ReadKey(); } } }
Результат
AD1 => 2.4 3.1 0.8 -2.2 0.9 11.6 AD2 => 3.8 11.7 -4.4 0.8 AD1 % AD2 = 2.850
⇑
Споріднені теми
- Перевантаження операторів. Загальні відомості. Перевантаження унарних операторів –, !, ++, —
- Перевантаження операторів порівняння ==, !=, >, <, >=, <=. Перевантаження логічних побітових операторів &, |, ^
⇑