Г. Шилдт - Полный справочник по C++ (1109478), страница 65
Текст из файла (страница 65)
Если обнаруживается перегруженный вариант оператора, опрсделснныи для конкретного класса, то вызывается именно эта версия, в противном случае применяется глобалы)ый оператор. Если глобальный оператор перегружен. выполпяготся сто псрегружснпьп, версии. Рассмотрим пример, в котором операторы пеы и йезеее перегружены глобально. азпс1ийе <1овстеаш> $1пс1ийе сясй11Ь> $1гс1ийе <пен> ивтпд пашеврасе вей; с1авя 1ос гпс 1опдаеийе, 1ас1сийе; риЬ11с: 1ос() () 1ос (1пс 1д, 1пс 1с) [ 1опд1еийе = 1д; 1асасийе = 1с) ) чо ай япон ( ) соне «1опдасис(е « соис « 1асзаийе « "~п"; ) )' // Глобальный оператор пею чоай *орегасот пеы(ядте с в1те] човй *р; р = ша11ос(вате) ат(!Р) ( Ьай а11ос Ьа; спеси Ьа; ) теситп р; ) // Глобальный оператор йе1еее чоЫ оретасот йе1есе(чозй *р! Гене(Р)' ) зпс шаап() ( 1ос *р1, "р2' 11оае *Х; сту ( р1 = пем 1ос (10.
20); сассЬ (Ьай а11ос ха) соил « "Ошибка прн выделении памяти для объекта р1. 1п"; Глава 15. ()врвгрузаа операторов гесогп 1;; ) у ( р2 = пеи 1ос (-10, -20); ) ласси (Ьас) а11ос ха) [ сопс кк " Опибка при выделении памяти для объекта р2.хп"; геспхг1 1;; ) ггу ( 1 = пои 11оаг; // ипользуется перегруженная версия /! огератора пеи сассп (Ьаб а11ос ка) ( соус <г " Оюибка при выделении памяти лля объекта Г.хп гебагп 1;; ) *Е = 10.)ОУ: сонг «*1 « 'хп'; р)->вбок(); р2->вбок(); с)е1еге р1; г)е1есе р2; с(е1еге 1; гесихп 0; ) Запустите зту программу и убедитесь, что для встроенных типов действительно вызываются перегруженные операторы пем и Ве1еее.
Перегрузка операторов пенн и бе!е$е для массивов Если вы хотитс определить свою собственную систему распределения памяти для массивов, необходимо еше раз перегрузить операторы пеи и ае1еее так, как показано ниже. // Вазмецение массива объектов. чогб *орехасох пеи()(вате г егге) ( /* Выделяется память. При отказе генерируется исключительная ситуация Ьаб а11ос. Конструктор каждого элемента вызывается автоматически. "/ гегигп ро1псег со пожогу: ) // удаление массива объектов чо10 орегагог бе1еге()(чона 'р) ( /* Освобождается память, на которую ссылается указатель р.
Деструктор каждого элемента вызывается ав оматически. */ ) Часть Н. Язык С++ После размещения массива в памяти для создания казкдого из его элементов автоматически вызывается конструктор. При освобождении памяти для уничтожения каждого объекта автоматически вызывается деструктор Для этих действий не обязательно предусматривать отдельный код. Следуюшая программа размешает в памяти массив объекта класса 1ос, а затем освобождает занятую память. З?пс1ийе <Ыясгеаи> $1пс1ийе <сясй11Ь> Фапс1ийе <пеи> ияжд паиеярасе ягйг с1аяя 1ос ( Ыс 1опд?сийе, 1асксийе; риЬ11с: 1ос() (1опдасийе = 1аскеийе = О; ) 1ос(Ыс 1д, 1пс 1с] ( 1опд1сийе = 1д; 1аейсийе = 1с; ) усЫ яиои ( ] ( соис «1огдасийе « соис «1асьеийе « "1п"; ) уоъй *орегасог пеи(яъге с яъяе] уоЫ орегасог йе1еее(чоЫ *р); чоай *орегасог пеи[) (вазе с вате) уоЫ срегасог йе1еее[) (чоЫ *р] г )г // Перегруженный оператор пеи лля класса чоЫ 1ос::орсгасог пеи(я?яе е я1яе) ( чоЫ *рг соис « "Внутри перегруженного оператора пеи.хп"] р = иа11ос(я1ге)г 1г(]р) ( Ьай а11ос Ьаг сигом Ьа; ) геглгп рг ) // Перегруженнь>г оператор йе1еее лля класса 1ос.
уоай 1ос::орегасог йе1еее(уоЫ *р) соне « "Внутри перегруженного оператора йе1еее.хп"] ггее(Р)г ) // Перегруженный оператор пеи лля размел?ения в памяти // массива объектов класса 1ос. Глава 16. Перегрузка операторов а )' чсхй '1ос::орехасох пем() (в).же с вххве) т ° о ай *р соис « "Применение перегруженного оператора пеи(). 1п"; | ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ е а ~ ~ ~ а !( р = ыа11ос(зхзе); (т('р) ( Ьай а11ос Ьа; Сихов Ьа; хеспхп р; ) Лерегруженнык оператор пем лпя размеггения в памяти массива объектов класса 1ос. чотй 1ос::орехасох йе1есе[)(чсхй <р) г сов' « "Упеление мессина с помо... ъю сперагора йе)ехе')) хп"; атее(р); хпс таха() ( 1ос 'р1, *р2, апх 1; сху р) =- пеи 1ос (10 20) // Газмеааем объект в памяти ) са(сЬ (Ьай а11ос ка) ( сопх « "Оыибка при выявлении памяти ЛЛЯ объекта р1.1п'; хеспхп 1~~ ) р2 = пеи 1ос (10): // Размеиаем массив в памяти ) сассЬ (Ьай а11ос ха) свое « " быибка при выявлении памяти лля объекта р2.
)п хеспхп 1;; ) р)->виом(); бох(х=О; 1<10; 1<.~) р2(х).виом(); йе1есе р1; // Уничтожаем сб ект йе1ехе () р2; // Уничтожаем массив хехпхп О; Перегрузка операторов пе))ч и бе1е$е, не генерирующих исключительной ситуации рассмотрим перс)рузку операторов пем и йе1еее, не генерирующих исключительной ситуации. Часть 11.
Намк С++ // Версия оператора пеи, не генерируююегс исключительной ситуации. чоЫ *сретаест пеи(в1те С втте, сспвс псеЬтои с ап) ( // Вылеплен память. 1Е(успешно) гегпгп укозотнсль но облостоь конягин; е1ве гегптп сз // Версия оператора пем, не генерирукщегс исключительнои ситуации, лля размещения массивов. чсЫ *сретасст пеи[)(вьте г в1те, сопев псе)зтси с ьп) ( // Выделяем память.
11 (уснсисно) тесптп укозаслсль~на область ванятки; е1ве теспгп О; ) чс1с сретасст бе1есе(чоЫ "р, сспвс пссптси с ьп) ( // ссвсбсвлаеьз память ) чс1с) сретасст с)е1есе[) (чстб *р, попас пег)зтсм С ьп) // Освобс>даем память Тип повитом е определен в заголовке <пем>. Он является типом объектов псе)зтом. Параметры типа псе)зтои е не используются. '~2 Перегрузка некоторых специальных операторов В языке С++ существуют операторы индексирования элементов массива "() ", вызова функции "()" и доступа к члену класса '*->'*.
Зги операторы также можно перегружать„что порождает массу интересных возможностей. На перегрузку этих операторов распространяется одно общее ограничение: они должны быть нестатическими функциями-членами. Дружественные функции применять нельзя. Перегрузка оператора "цп При перегрузке оператор "()'* считается бинарным. Следовательззо. он должен иметь ~акой вид: изин иня класси::срегасст [) (Впс т) з ( // С технической точки зрения параметр не обязан иметь тип 1пе, однако функция орегаест() () обычно применяется лля индексирования элементов массива, поэтому чаще всего используют именно целочисленный параметр.
Допустим, что объект называется о. Тогда выражение Я о[з) Глава 15. Перегрузка оператороа преобразуется в следующий вызов Функции орвтаеотц () з 'г О.срвтатот!)(3) Иначе говоря, значение выражения, заключенного в квадратные скобки, передастся функции оретаес т[] () в качестве явного параметра. Указатель е]ххя ссылается на обьскт о, который генерирует вызов Функции. В слслуюшсй программе класс аезгрв содержит массив, состоящий из трех элементов. Его конструктор инициализируез. каждый элемент массива отдельным значением.
Перегруженная операторная функция оретаеот() [] возвращает значение элемента массива по заданному индексу. Фзпс1ис]е <хояетеаы> ивзпя пазявврасе вес]з с1авв атурв ( ьпс а[3]з р .Ь1хс з асурв(хпс х, хпс 3, хпс к) а[0] = з.з а[1) — - зз а [2) = )сз ) хпс оретасот[) (хпс 1) ( тесптп а[х]; ) )з хпт та[гз() ( асуре оЬ(1, 2, 3) з сопя « оЬ[1]; /у Выводит на экран число 2 тесптп Оз ) Функцию орвтаеох.() П можно определить таким образом, чтобы оператор "и" был допустимым и в левой, и в правой части оператора присваивания. Для этого нужно.
чтобы функция орвтаеот[]() возвращала ссылку. Продемонстрируем это с помощью следующей программы. Вхпс1псв <хоястяалз' паапа папзеврасе вес]з с1аяя асуре ( зпс а[3)з рпбьхсз асуре(ьпс х, з.пс 3, зпс К) а(О] = ьз а [1) а[2) = Ки ) хпс ьорятасат[] (зпс х) ( твсптп а[1); )з хпс жа1п() ( аеуре оЬ(1, 2, 3) З Часть И. Язык С~+ сопс « оЬ[11) // Выводит на экран число 2 соса « оЬ[1) = 25) // Оператор [) стоит слева сопс « оЬ[11; // Теперь на экран выводится число 25 гесигп 0; Поскольку теперь операторная функция орееасокц () возвращает ссылку на элемент массива с индексом 1, ее можно использовать в левой час~и оператора присваивания для модификации элементов массива. (Разумеется, оператор "[]" по-прежнему можно использовать в правой части оператора присваивания.) Перегрузка оператора "[) '* позволяет обеспечить контроль за выходом индекса массива за пределы допустимого лнапазона, который по умолчанию не предусмотрен в языке С++.
Создав класс, содержащий массив, и прелусмотрев перегруженный оператор "[1", можно перехватить возникающую исключительную ситуацию. Рассмотрим пример, в котором программа предусматривает проверку диапазона индексов массива. // Пример безопасного массива. Мьпс1пде <ьоясгеаи> Етпс1пс)е <сясо11Ь> пяьпд патеярасе веры с1аяя асуре ( 1пс а[31; рпЬ11с: асуре(1пс 1, ьпс 3, ызс )<) а[01 = ью а[11 = зю а[2) = К; ) хпс ьорегасог[](1пс 1); ); // Проверка диапазона изменения индекса для класса аеуре. 1пс аасуре::орегасог[)(1пс 1) ( 15(1<0 )) 1> 2) ( соне « "Выход за пределы допустимого диапазона1п"; ехьс(1); ) геспгп а[11) ) хпс иаыт() ( аеуре оЬ(1, 2, 3) г соус « оЬ[11) // Выводит на экран число 2 сопс « оЬ[1) = 25; // Оператор [] слева соне « оЬ[1)) // Выводит на экран число 25 Глава 15.
Перегрузка операторов оп(3) = 44; Г! Генерируется опибка, эиачение 3 ~/ лежит вие допустимого диапазона .-- япт 0. При выполнении оператора фупкция орееаеож() () перехватывает возиикшую исключительную ситуацию и прекращает выполпенис программы. (На практике выполпспис программы обычно не прекращается. а вместо этого вызывается обработчик исключительпои ситуации. связаппой с выходом иплскса за пределы допустимого лиапазоиа.) Перегрузка оператора иОи При перегрузке оператора "П" созлается операторная функция, которои можно псрславюь произвольное количество параметров.
При этом новый способ вызова фупкции па самом деле цс создается. Рассмотрим пример. Допустим, что оператор вызова фупкции перегружен в некотором классе слелуюшим образом: и йопЬ1е оретаеот() (1пе а, Й)оае Е, спас "в); Кроме того, предположим, что переменная о является объектом этого класса. Тогда оператор Я О( О, 23.34, "Привет" ); преобразуется в следующий вызов операторной функции орееаеое (): и О.орете'оп()(10, 23.34, "Привет" ); Как правило. при перегрузке оператора "()" определяются параметры. передаваемые функции.