Г. Шилдт - С#4.0 Полное руководство (1160795), страница 51
Текст из файла (страница 51)
всасас роЬ1гс Ъоо1 1войб(с)опЬ|е пош) ( гесигп !1зкчеп(пиш); ) с1ааз ЯсасгсС1аввоешо ( агаг1с чо1г) Маги() ( Сопзо1е.нг1геЬ1пе("Обратная величина числа 5 равна " + Ипшег1срп.вес1ргоса1(5.0)); Сопао1е.нг1сеЬ1пе("Дробная часть числа 4.234 равна " ИпшеггсГп.ГгасРагс(4.234))) 11(нпшеггсГп.1зЕчеп(10)) Сопэо1е.нг1сеЬгпе("10 — четное число.") 11 (Ипшег1сгп. 1эойб (5) ) Сопво1е.нг1ге11пе("5 — нечетное число.") // Далее следует попытка создать экземпляр объекта класса Ичшеггсрп, // что может стать причиной появления ошибки.
// Ипшеггсгп оЬ = пен Ипшеггсгп(); // Ошибка! Пот к какому результату приводит выполнение этой программы. Обратная величина числа 5 равна 0.2 Дробная часть числа 4.234 равна 0.234 10 — четное число. 5 — нечетное число. 268 Часть й Язык С$ Обратите внимание на то, что последняя строка приведенной выше программы закомментирована. Класс Мшвет1оЕо является статическим, и поэтому любая попытка создать объект этого класса может привести к ошибке во время компиляции. Ошибкой будет также считаться попытка сделать нестатическим член класса Ншвегтсв'и. И последнее замечание: несмотря на то, что для статического класса не допускается наличие конструктора экземпляра, у него может быть статический конструктор. 270 Часть ).
язык СФ Основы перегрузки операторов Перегрузка операторов тесно связана с перегрузкой методов. Для перегрузки оператора служит ключевое слово орет а сот, определяющее операп1орный згегпод, который, в свою очередь, определяет действие оператора относительно своего класса. Существуют две формы операторных методов (оре гасо г): одна — для унарных операторов, другая — для бинарных. Ниже приведена общая форма для каждой разновидности этих методов.
Общая форма перегрузки унарного оператора. рпбггс зсаггс возвращаемый тип орегагог ор)тип параметра операнд) ( операции ) Общая форма перегрузки бинарного оператора. рцЬ11с зсасгс возвращаемый тип орегасог ор)тип параметра1 операнд1, тип парамотро1 операндг) ) операции Здесь вместо ор подставляется перегружаемый оператор, например + или /; а возвращаемый тип обозначает конкретный тип значения, возвращаемого указанной операцией.
Это значение может быль любого типа, но зачастую оно указывается такого же типа, как и у класса, для которого перегружается оператор. Такая корреляция упрощает применение перегружаемых операторов в выражениях. Для унарных операторов операнд обозначает передаваемый операнд, а для бинарных операторов то же самое обозначают операнд1 и операнд2. Обратите внимание на то, что операторные методы должны иметь оба типа, рцЬ11с и згагйс, Тип операнда унарных операторов должен быть таким же, как и у класса, для которого перегружается оператор.
А в бинарных операторах хотя бы один из операндов должен быть такого же типа, как и у его класса. Следовательно, в О) не допускается перегрузка любых операторов для объектов, которые еще не были созданы. Например, назначение оператора + нельзя переопределить для элементов типа 1пг или з Сгйпо. И еще одно замечание: в параметрах оператора нельзя использовать модификатор гег или оцг. Перегрузка бинарных операторов Для того чтобы продемонстрировать принцип действия перегрузки операторов, начнем с простого примера, в котором перегружаются два оператора — + и —. В приведенной ниже программе создается класс Тпгее)), содержащий координаты объекта в трехмерном пространстве. Перегружаемый оператор + складывает отдельные координаты одного объекта типа тпгеео с координатами другого.
А перегружаемый оператор — вычитает координаты одного объекта из координат другого. Пример перегрузки бинарных операторов. озьпс Зузсещг риЫТс Тпгееб() ( х = у = я = 01 ) риЫ1с ТЬгееО(1пг 1, Тпг 0, Тпг К) ( х = 1; у = 0; г = ум ) // Перегрузить бинарный оператор риЬ11с яоаоас ТЬгеео орегасог +(ТпгееО ор1, ТЬгееО ор2) ( ТпгееО геяи1С = пен ТпгееР() 1 /* Сложить геяи1г.х = геяи1г у = геяи1г.г координаты двух точек и возвратить результат. */ ор1.х + ор2.х) // Эти операторы выполняют ор1.у + ор2.у) // целочисленное сложение, ор1.г + ор2.я; //сохраняя свое исходное назначение.
гегигп геяи1г) ) // Перегрузить бинарный оператор — . риЫТс ясасас ТЬгееО орегасог †(Тпгеео ор1, Тпгее0 ор2) ( ТЬгееО геяи1Г = пен ТЬгееО()г /* Обратите внимание на порядок следования операндов: ор1 — левый операнд, а ор2 — правый операнд. */ геяи1с.х = ор1.х — ор2.х) // Эти операторы геяи1о.у = ор1.у — ор2.у; // выполняют целочисленное геяи1Ы я = ор1.я — ор2.я( // вычитание гесигп геяи1ГГ ) // Вывести координаты Х, у, Е.
риЫ1с чо1б ЯЬон() ( Сопяо1е.кглсе11пе(х + ", " + у е ", " + я) ) ) ) // Класс для хранения трехмерных координат. с1аяя ТЬгее0 ( апг х, у, я; // трехмерные координаты с1аяя ТЬгееООеюо ягаг1с чо16 Малп() ( ТпгееО а = пен ТпгееО(1, 2, 3)г ТпгееО Ь = пен ТпгееО(10, 10, 10) ТЬгееО с; Сопяо1е.Игусе("Координаты точки а: "); а.япон(): Сопяо1е.нг1сеЬгпе() 1 Сопяо1е.нг1се("Координаты точки Ь: ") Ь.ЯЬон(): Сопяо1е.пгзсе01пе(); Глава 9. Перегрузка операторов 271 272 Часть!. Язык С№ с = в + Ь; // сложить координаты точек а и Ь Сопвс1е.нг1ге("Результат сложения а + Ь: с.здон(): Сопво1е.Хгьгевьпе(); с = а + Ь + с; // сложить координаты точек а, Ь и с Сспвп1е.нг1пе("Результат сложения в + Ь + с: с.зьон(); Сопвп1е.ыгьвеъьпе(); а; // вычесть координаты точки а .Хттде("Результат вычитания с — а: .Хггсеъгпе()( с=с Сопво1е с.зЬсн( Сспзо1е с = с — Ь„.
// вычесть координаты точки Ь Сопво1е.нггпе("Результат вычитания с — Ь: с.зЬпн(); Сппзп1е.Хтьпешпе(); При выполнении этой программы получается следующий Результат. Координаты точки в: 1, 2, 3 Координаты точки Ь: 10, 10, 10 Результат сложения а + Ь: 11, 12, 13 Результат сложения а + Ь + с: 22, 24, 26 Результат вычитания с — а: 21, 22, 23 Результат вычитания с — Ь: 11, 12, 13 Внимательно проанализируем приведенную выше программу, начиная с перегружаемого оператора т. Когда оператор + оперирует двумя объектами типа ТЬгееР, то величины их соответствующих координат складываются, как показано в объявлении операторного метода ореха сог+ ( ) .
Следует, однако, иметь в виду, что этот оператор не видоизменяет значения своих операндов, а лишь возвращает новый объект типа тпг ее Р, содержащий результат операции сложения координат. Для того чтобы стало понлтнее, почему операция + не меняет содержимое объектов, выступающих в роли ее операндов, обратимся к примеру обычной операции арифметического сложения: 10+ 12.
Результат этой операции равен 22, но она не меняет ни число 10, ни число 12. Несмотря на то что ни одно из правил не препятствует перегруженному оператору изменить значение одного из своих операндов, все же лучше, чтобы действия этого оператора соответствовали его обычному назначению. Обратите внимание на то, что метод орегагогт () возвращает объект типа тЬгееР. Этот метод мог бы возвратить значение любого допустимого в С)) типз3 но благодаря тому что он возвращает объект типа тЬгееР, оператор + можно использовать в таких составных выражениях, как а+Ь+с.
В данном случае выражение а+Ь дает результат типа тЬгееР, который можно затем сложить с объектом с того же типа. Если бы Глава 9. Перегрузка операторов 273 выражение а+Ь давало результат другого типа, то вычислить составное выражение а»-Ь»-с было бы просто невозможно. Следует также подчеркнуть, что когда отдельные координаты точек складываются в операторе орегагога (), то в результате такого сложения получаются целые значения, поскольку отдельные координаты х, у и з представлены целыми величинами. Но сама перегрузка оператора + для объектов типа ТЬгееР не оказывает никакого влияния на операцию сложения целых значений, т.е.
она не меняет первоначальное назначение этого оператора. А теперь проанализируем операторный метод орегасог — () . Оператор — действует так же, как и оператор Ь но для него важен порядок следования операндов. Напомним, что сложение носит коммутативный характер (от перестановки слагаемых сумма не меняется), чего нельзя сказать о вычитании: А — В не то же самое, что и  — А) Для всех двоичных операторов первым параметром операторного метода является левый операнд, а вторым параметром — правый операнд. Поэтому, реализуя перегружаемые варианты некоммутативных операторов, следует помнить, какой именно операнд должен быть указан слева и какой — справа.
Перегрузка унарных операторов Унарные операторы перегружаются таким же образом, как и бинарные. Главное отличие заключается, конечно, в том, что у них имеется лишь один операнд. В качестве примера ниже приведен метод, перегружающий оператор унарного минуса для класса ТЬгее0. О Перегрузить оператор унарнсго минуса. рпбгьс згаг1с ТпгееР срегассг †(ТЬгееО ср) ( ТпгееО геаи1Г = пан ТпгааО(); гази1г.х = -ср.х; гези1Г.У = ср у: Гаас1Г.
Е = ОРаж гесигп гезн1г; ) В данном примере создается новый объект, в полях которого сохраняются отрицательные значения операнда перегружаемого унарного оператора, после чего этот объект возвращается операторным методом. Обратите внимание на то, что сам операнд не меняется. Эго означает, что и в данном случае обычное назначение оператора унарного минуса сохраняется, Например, результатом выражения а=-Ь является отрицательное значение операнда Ь, но сам операнд Ь не меняется. В С)) перегрузка операторов»-»- и — — осуществляется довольно просто. Для этого достаточно возвратить инкрементированное или декрементированное значение, но не изменять вызывающий объект. А все остальное возьмет на себя компилятор СФ, различая префиксные и постфиксные формы этих операторов. В качестве примера ниже приведен операторный метод орегасог»-+ () для класса ТЬгееР.
274 Часть!. Язык С№ // Перегрузить унарный оператор ++. риЬ11с ягаггс ТЬгеео орегагог ++(ТЬгееО ор) ( ТЬгеео геяи1С = пен ТЬгееО()) // Возвратить результат инкрементирования. геяи1С.х ор.х + 1; геяи1с.у = ор.у + 1; геяи1г.г = ор.г + 1; гесигп геяи1с) ) Ниже приведен расширенный вариант предыдущего примера программы, в кото ром демонстрируется перегрузка унарных операторов — и ++. // Пример перегрузки бинарных и унарных операторов. изгнав Вуягеит // Класс для хранения трехмерных координат. с1аяя ТЬгеео ( гпс х, у, г; // трехмерные координаты риЬ1гс ТЬгеео() ( х = у = г = О; ) рис11с ТЬгееО(гпС 1, Тпг 1, 1пС )с) ( х = 1; у = 2; х = )ы ) // Перегрузить бинарный оператор +. рив11с ятаС1с ТЬгеео орегагог ь(ТЬгеео ор1, Тлгеео ор2) ( ТЬгеео геяи1С = пен ТЬгеео()) /* Сложить координаты двух точек и возвратить результат.
*/ геяи1г.х = ор1.х + ор2.х; геяи1г.у = ор1.у + ор2.у; геяи1С.я = ор1.я + ор2.я; гесигп геяи1с/ ) // Перегрузить бинарный оператор — . ривггс вгаггс Твгеео орегагог -(ТЬгеео ор1, ТЬгееО ор2) ( ТЬгееО геяи1С = пен ТЬгеео(); /* Обратить внимание на порядок следования операндов: ор1 — левый операнд, ор2 — правый операнд. */ геяи1с.х = ор1.х - ор2.х; геяи1С.у = ор1.у — ор2.у; геяи1С.х = ор1.я — ор2.г; гетигп геяи1С( // Перегрузить унарный оператор риЬ1гс ятаС1с ТЬгеео орегагог †(ТЬгеео ор) Гаааа 9. Пере(руана операторов 276 ( ТпгееО геви1Г = пен ТпгееР() гевч1с.х = -ор.х; геви10.у = ор у) гево1г. г = ор ° 2 ' гесигп гевп1Г; ) О Перегрузить унарный оператор ++.