Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Вопрос? Перегрузка операторов в C#


Автор: Neuromancer 29.8.2006, 15:27
Читаю книгу “Шилдт Полный справочник по С#”

У меня вопрос? Я не хрена не понял, что там Шилдт наколбасил про перегрузки операторов, 
мог бы кто нибуть объяснить поподробней, кое-что, конечно, понял, но не все.

И если можно, то приведите пример с комментариями или ссылку дайте, где можно
прочитать, чтоб там все понятно расписано было и cпримерами.

Автор: marcusmae 29.8.2006, 16:04
Ссылок http://www.google.com/search?client=opera&rls=ru&q=c%23+operator+overloading&sourceid=opera&ie=utf-8&oe=utf-8. А вообще, вряд ли сильно много умеющих объяснить лучше Шилдта. smile
То есть, имеет смысл задать более конкретные вопросы о том, что непонятно. Мы попробуем ответить ;)

Автор: reloni 29.8.2006, 18:24
Цитата(marcusmae @  29.8.2006,  16:04 Найти цитируемый пост)
А вообще, вряд ли сильно много умеющих объяснить лучше Шилдта

Это точноsmile
Но вот пример, практически под копирку списанный у Троелсена, может он поможет:
Код

public class Point
{
    private int _x;
    private int _y;

    public Point(int x, int y)
                {
        this._x = x;
        this._y = y;
    }

    public int X
    {
        get { return this._x; }
    }

    public int Y
    { 
        get { return this._y; } 
    }

    // собственно перегрузка оператора +
    public static Point operator +(Point cl1, Point cl2)
    {
        return Add(cl1, cl2);
    }

    private static Point Add(Point cl1, Point cl2)
    {
        return new Point(cl1.X + cl2.X, cl1.Y + cl2.Y);
    }

    // перегрузка оператора -
                public static Point operator -(Point cl1, Point cl2)
    {
        return Sub(cl1, cl2);
    }

    private static Point Sub(Point cl1, Point cl2)
    {
        return new Point(cl1.X - cl2.X, cl1.Y - cl2.Y);
    }

    // переопределяем метод ToString для простоты вывода на консоль
    public override string ToString()
    {
        return "X= " + this.X.ToString() + ", Y= " + this.Y.ToString();
    }
}


Перегрузки "+" и "-" вызывают соответственно методы Add и Sub, в принципе можно и не плодить дополнительных методов. Эти метды возвращают новый класс, с измененными координатами. Теперь можно написать:

Код

Point cl1 = new Point(1, 5);
Point cl2 = new Point(-8, 10);
Point cl3 = cl1 + cl2;
Console.WriteLine(cl3.ToString());

Автор: marcusmae 29.8.2006, 18:53
smile Тогда, чтобы было совсем понятно, добавлю, что в 

Код

    // переопределяем метод ToString для простоты вывода на консоль
    public override string ToString()
    {
        return "X= " + this.X.ToString() + ", Y= " + this.Y.ToString();
    }


override потому что подразумевается переопределение метода, унаследованного классом Point  от System.Object :

Код

public class Point : System.Object


который определяет методы GetType(), ToString(), Equal(), GetHashCode() и др. :

Код

    // из метаданных
    public class Object
    {
        public Object();

        public virtual bool Equals(object obj);
        public static bool Equals(object objA, object objB);

        public virtual int GetHashCode();
        public Type GetType();

        protected object MemberwiseClone();
        public static bool ReferenceEquals(object objA, object objB);

        public virtual string ToString();
    }


и ещё, функции перегрузки операторов всегда статические (static). То есть, общие для всех экземпляров класса Point.

Автор: ivashkanet 30.8.2006, 09:47
reloni, попробую я немного объяснить smile

На примере операции "+".
Этот символ обозначает разные операции.
Например 1+1 --- опирация сложения чисел (ответ 2)
А если "1" -- строка, то + будет складывать именно строки, а не их значения. 
Алгоритм этого действия другой и в ответе уже будет "11" -- склейка этих строк.

Получается, что результат одной и той же операции зависит от того что мы складываем (это естественно).

По умолчанию, язык C# не в курсе как складываются точки (Point).
Поэтому его нужно этому учить:
Код
public static Point operator +(Point cl1, Point cl2)

Внутри ты можешь поставить любую реализацию (даже попарно умножить их).
Мы только что научили C# складывать Точки.
Можно научить умножать Точку на число:
Код
public static Point operator *(int cl1, Point cl2)

Можно эту же операцию применить к скалярному умножению точек:
Код
public static int operator *(Point cl1, Point cl2)

И так далее....
В последних двух примерах мы и сталкиваемся с перегрузкой. 
Т.е. Когда один и тот же оператор (*) имеет разные реализации (но!, что важно для разных аргументов).

Как же компилятор определяет какую реализацию выбрать?
Очень просто:
Если ты перемножаешь число и Точку (именно в этом порядке smile ), то нужно выбирать первую реализацию, если две точки, то вторую.
Код

Point cl1 = new Point(1, 5);
Point cl2 = new Point(-8, 10);
int i = 5;

Point cl3 = i * cl2; // Можно было написать 5 * cl2
// cl3 = cl2 * i  --- выдаст ошибку компиляции, ведь мы не написали (не определили), 
// что делать если первый параметр точка, а второй число  :thumbs-up 

int j = cl1 * cl2;



Автор: Neuromancer 30.8.2006, 11:48
ivashkanet- Спасибо тебе огромное вот люди учитесь, как надо объяснять.  smile 

Автор: ivashkanet 30.8.2006, 11:50
Neuromancer, не за что  smile

Автор: VisualProgrammerNET 30.8.2006, 14:56
Никогда не любил заморачиваться с этими операторами... проще написать один метод типа 
Код

static Point SumPoints(Point p1, Point p2). 

 smile 

Автор: reloni 30.8.2006, 15:08
VisualProgrammerNET, ингда бывает проще написать
Код

p3 = p1 + p2;

Чем вызывать каждый раз статический метод. Особенно если это надо делать часто.

Автор: $tatic 2.9.2006, 13:56
Для векторов и матриц к тому же полезно. Хотя для векторов и существует два типа умножения.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)