Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Добавление дополнительных перегрузок
В дополнение к сложению векторов, можно было бы умножать и вычитать их, а также сравнивать между собой. В настоящем разделе мы продолжим развитие примера Vector, добавив еще несколько перегрузок операций. Сейчас мы не станем разрабатывать полный набор, который, вероятно, понадобился бы для полнофункционального типа Vector, а просто продемонстрируем другие аспекты перегрузки операций. Для начала перегрузим операцию умножения, чтобы добавить поддержку умножения векторов на скаляры и векторов на другие векторы. Умножение вектора на скаляр означает просто индивидуальное умножение каждого его компонента на скаляр; например, 2*(1.0,2.5,2.0) вернет (2.0,5.0,4.0). Соответствующая перегрузка операции выглядит следующим образом: public static Vector operator* (double lhs, Vector rhs) { return new Vector(lhs*rhs.x, lhs*rhs.y, lhs*rhs.z); } Однако этого недостаточно. Если а и b объявлены как Vector, то это позволит написать код вроде такого: b = 2 * а; Компилятор просто неявно преобразует целое число 2 в double, чтобы выражение соответствовало сигнатуре перегрузки. Однако следующий код не скомпилируется: b = а * 2; Дело в том, что компилятор трактует перегруженные операции точно так же, как перегрузку методов. Он проверяет все доступные перегрузки данной операции, чтобы отыскать наиболее подходящий. Приведенный выше оператор требует, чтобы первый параметр имел тип Vector, а второй - целое число либо нечто, неявно преобразуемое в целое. Но мы не предоставили такой перегрузки. Компилятор не может поменять местами параметры, хотя в данном случае их порядок не важен. Придется явно определить перегрузку, которая принимает сначала Vector, а потом - double. Существуют два способа ее реализации. Первый способ предполагает написание операции умножения вектора на число точно так же, как это было сделано в первом случае: public static Vector operator* (Vector lhs, double rhs) { return new Vector(rhs * lhs.x, rhs * lhs.y, rhs *lhs.z); } Но, имея уже написанный код, реализующий в точности ту же операцию, эффективнее его использовать повторно: public static Vector operator* (Vector lhs, double rhs) { return rhs * lhs; } Этот код сообщает компилятору, что если он видит умножение Vector на double, то может просто поменять порядок операндов и вызвать другую перегрузку. Какому варианту отдать предпочтение - дело вкуса. В примерах настоящей главы используется вторая версия, поскольку она выглядит проще и лучше иллюстрирует идею. Эта версия также облегчает сопровождение, поскольку позволяет избежать дублирования кода умножения в двух отдельных перегрузках.
Далее понадобится перегрузить операцию умножения для поддержки перемножения векторов. Математики предлагают множество способов перемножения векторов, но нас интересует один, известный как скалярное произведение, который возвращает в результате скаляр. Это повод продемонстрировать на данном примере, что арифметические операции не обязаны возвращать тип, совпадающий с типом класса, в котором они определены. В математической терминологии, если есть два вектора - (х,у,z) и (X,Y,Z), - то значение их скалярного произведения определяется как результат выражения х*Х + y*Y + z*Z. Это может показаться странным способом перемножения таких двух вещей, но на самом деле он довольно полезен, поскольку может применяться для вычисления множества других показателей. Конечно, если вы пишете код, отображающий сложную трехмерную графику, например, использующую Direct3D или DirectDraw, то почти наверняка обнаружите, что скалярное произведение векторов понадобится для вычисления положения объектов на экране. Что сейчас нас интересует - так это дать возможность людям, использующим класс Vector, писать выражения вроде double X = а * b для вычисления скалярного произведения двух объектов Vector (а и b). Соответствующая перегрузка будет выглядеть так: public static double operator * (Vector lhs, Vector rhs) { return lhs.x * rhs.x + lhs.у * rhs.у + lhs.z * rhs.z; } Теперь, когда мы разобрались с арифметическими операциями, можно проверить их работоспособность с помощью простого тестового метода: static void Main() { // демонстрация арифметических операций Vector vect1, vect2, vect3; vect1 = new Vector (1.0,1.5,2.0); vect2 = new Vector(0.0,0.0,-10.0); vect3 = vectl + vect2; Console.WriteLine("vect1 = " + vect1); Console.WriteLine("vect2 = " + vect2); Console.WriteLine("vect3 = vect1 + vect2 = " + vect3); Console.WriteLine("2*vect3 = " + 2*vect3); vect3 += vect2; Console.WriteLine("vect3 += vect2 дает " + vect3); vect3 = vect1*2; Console.WriteLine("Присваивание vect3 = vect1*2 дает " + vect3); double dot = vect1*vect3; Console.WriteLine("vectl*vect3 = " + dot); } Запуск этого кода (Vectors2. cs) даст следующий результат:
vect1 = (1, 1.5, 2) vect2 =(0, 0, -10) vect3 = vectl + vect2 = (1, 1.5, -8) 2*vect3 = (2, 3, -16) vect3 += vect2 дает (1, 1.5, -18) Присваивание vect3 = vectl*2 дает (2, 3, 4) vect1*vect3 = 14.5 Вывод показывает, что перегруженные операции выдают корректные результаты, но если посмотреть на тестовый код внимательно, то можно удивиться, заметив, что он использует операцию, которая не была перегружена, а именно - операцию сложения с присваиванием, +=. vect3 += vect2; Console.WriteLine("vect3+=vect2 дает " + vect3); Хотя += обычно считается единой операцией, она может быть разбита на два отдельных шага: сложение и присваивание. В отличие от языка C++, в C# на самом деле не разрешено перегружать операцию =, но если вы перегрузите операцию +, то компилятор автоматически использует эту перегрузку и в операции +=. Тот же принцип применим ко всем операциям присваивания, т.е. -=, *=, /=, &= и т.д.
|
||||||
Последнее изменение этой страницы: 2016-12-30; просмотров: 131; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.139.107.241 (0.007 с.) |