Перегрузка бинарных операторов. Перегрузка операторов +, –, *, /, %. Вложение произвольной логики при перегрузке
Перед изучением данной темы рекомендуется ознакомиться со следующей темой:
Содержание
- 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
⇑
Связанные темы
- Перегрузка операторов. Общие сведения. Перегрузка унарных операторов. –, !, ++, —
- Перегрузка операторов сравнения ==, !=, <, >, <=, >=. Перегрузка логических побитовых операторов
⇑