Г. Шилдт - Полный справочник по C++ (1109478), страница 59
Текст из файла (страница 59)
В динамической памяти можно разместить массивы объектов, однако следует иметь в виду олпу ловушку. Массивы. размещенные в динамической памяти с помощью оператора па>г, нельзя инициализировать, поэтому следует убедиться, что класс содержит конструктор, не имеющий параметров. В противном случае компилятор языка С++ нс найдет подходящего конструктора и при попытке разместить массив в динамической памяти выдаст сообщение об ошибке.
В следующей версии нашей программы в динамической памяти размещается массив ьа1апсе, и вызывается конструктор, ис имеющий параметров. аьпс1ибе «1овххеаю> В1пс1иба <пен> Вфпс1иде ссвсхапд> ивьпд патеврасе вхйг с1авв Ьа1апсе боиЬ1е сих Ьа1; спал паве[80] г риЬ) ас г Ьа1апсе(бо1зЬ1е и, спах *в) сих Ьа1 = и; вг хору(лазая, в); ) Часгь й. йзык С++ Ьа1апсе() () // Конструктор без параметров -Ьа1апсе() сочв « "Уничтожение объекта сопс «паже « "1п"; чотб вес(г]ооЬ1е и, сЬаг *в) ( сот Ьа1 = лг вггсру(паже, я)г ) чоЫ дес Ьа1(доибзе ап, спаг *з) и = спг Ьа1; вггсру(в, папе); ) )г ьпе щагп! ) ( Ьа1апсе *р; спаг в(80)г доиЬ1е пг Рпс 1; сгу ( р = пеи Ьа1апсе [3]г // Размещение массива ) сассЬ (Ьаг] а11ос ха) ( соос « "исключительная ситуаиия1п"г гесигп 1; ) // Используется оператор ., а не -> р[0).вег(12387.87, "Ральф уилсон")г р[1).яеС(144.00„ "А.
С. Коннерс )г р[2).зес(-11.23, "и. и. Овердроун")г гог(1=0г 1<3г 1++] ( р[1).дес Ьа1(п, в)г соус « я « ": сумма = " « пг соне « "1п"г г)е1еее [) Рг гесигп Ог ) В результате работы этой программы на экран будут выведены слеаугошие строки. Ральф Уилсон: сумма = 12387.9 А. С. Коннерс: сумма = 144 И. М. Овердроун: сумма = -11.23 Уничтожение объекта И.
М. Овердроун Уничтожение объекта А. С. Коннерс Уничтожение объекта Ральф Уилсон Для уничтожения массива динамических обьектов следует применять оператор ((е1есе И, чтобы можно было вызыватьдеструктор для каждого обьскта отдельно. Глава 13. Массивы, уквввтвгм, ссылки и операторы дгывввчвскагс распределения лвмвтл Згу Альтернатива пойгов В сл)час ((схватки памяти опсрагор оем можст нс гснсрировать исключительную ситуацию, а возвращать нулевой указатсль.
Этот вил оператора пем оказывается вссьма полезным при работе со старыми компиляторами. Особснно цснно, что вызовы функции ые1- 1ос() можзю замснить опсратором пем. (Это часто приходится дслать при переводе программ с языка С з за язык Ст+.) Для этого применяется сззсдуюшая форма опсратора пем. В»казазззвль = пем(лог)злом) тнк; Эта форма опсратора ззем напоминаст ого раннис всрсии. Поскольку в случас нехватки памяти он нс генерирует исключительную ситуацию, а возврашаст нулевой указатель, ого можно внсдрять в старые программы. Однако в новых программах лучшс использовать новый вариаз(т оператора нем. гснсрируюший исключительную ситуацию Ьезт е11оо.
Чтобы иметь возможность использовать опцию пес)зком, следует включить в программу заголовок <оем>. Рассмотрим программу, дсмонсгрируюШую альтсрнативу нем(пес)зком) . // демонстрация альтернативы пеи(политом) Зьпс1цбе <зовгтеам> Мзпс1цбе <пем> цв1пд папзеврасе ввб; 1пс взазл() ( зззс *р, 1; р = лен(погпгои) 1пг(32); // Применение огзцми пог)злом ззб(.'р) ( соцг « "Исключительная ситуация. (л"з гегцз и 1 з ) бог(з.=-сз 5<32з 1>ь) р(з) = з.з бог('=Оз 1<32з 1++) соцс « р(1) « ь)е1еге () рз // Освобождаем память кесцгп О; ) Как показывает эта программа, при использовании альтернативы пес)зсом слсдуст провсряп указатель, возврашасмый опсрапзром пеьк Буферизованный оператор пее В языке Сч ь сушсствуст особая форма оператора оем, копзрую можно применять для >казания альтернативного способа распределения динамичсской памяти.
Эта форма называется гзузферзззовонззмм оператором пем (гор)ассгпсп( (опп об псез). Наиболее полезным это сродство оказывается при псрсгрузкс оператора лом в особых ситуациях. Его общий вид таков. В указатель = пеи (олззоок аргулзвнтов) тин; Здссь список аргументов прсдсгавляст собой псрсчислснис значении, разделанных за- пятыми, которые передаются псрсгружснному оператору пем. Часть!!. Язык С+) Полный спр 2ВОЧНИК ПО 1 1 1 Ф Перегрузка функции, и аргументы пО умОлчанию этой главе рассматриваются перегрузка функций, конструкторы копирования и аргу- В менты, задаваемые по уыолчанию. Лерегрузка функций — один из основных аспектов языка С++.
Она обеспечивает статический полиморфизм, а также гибкость и комфорт. Чаше всего перегрузке подвергаются конструкторы. Одной из наиболее важных форм перегрузки конструкторов является конструктор копирования. Возможность задавать аргументы по умолчанию используют в качестве альтернатины перегрузке функций. Перегрузка функций Лерегрузка функций — это использование одного имени для нескольких функций. Секрет перегрузки заключается в том, что каждое переопределение функции должно использовать либо другие типы параметров, либо другое их количество. Только эти различия позволяют компилятору определять.
какую функцию следует вызвать в том или ином случае. Например, в следующей программе функция мунцпс() перегружена для разных типов параметров. $1пс1це)е <1овсхеам> цв1пд паиеврасе во<); 1пе тупцпс(1пе 1); // Эти варианты различаются типами параметров с)оцЬ1е ыугцпсЫоцЬ1е 1); 1пс иа1п О ( соне «туецпс(1О) « " "; // Вызов функции тупцпс(1пе ).) соне «муыцпс(5.4); // Вызов функции иу1цпсЫоцЬ1е 1) хеецхп О; ) е)оцЬ1е муыэпс(с)оцЬ1е 1) ( хегцхп 1; ) 1пе иугцпс(1пе 1) ( хегпхп 1," ) В следующей программе перегруженные варианты функции иувцпс О используют разное количество параметров. $1пс1цс)е <1овехеат> цв1пд паиеврасе вМу 1пе ыу1цпс(1пс 1); // Эти варианты различахтся количеством параметров 1пе туыцпс(1пе 1, хпе 1); 1пс мафп() ( соне « му1цпс(10) « " "; // Вызов функции иугцпс(1пе 1) соне « ыу1цпс[4, 5); // Вызов функции ыу1штс(1пг.
1, 1пс >) Часть Я. Язык С++ хееихп О; ьпх тухипс(ьпс 1) ( хееихп 1; ) 1пе мухино(ьпе 1, 1пе з) ( хееихп 1*э; ) Следует помнить, что перегруженные функции должны отличаться типами или количеством параметров. Тип возвращаемого значения не позволяет перегружать функции. Например, следующий вариант перегрузки функции муеипс О неверен. ьпе кгубипс(зпе 1); // Ошибка: разных типов возвращаемого х1оас л1у- 1 гипс(1пе 1); // значения недостачно для перегрузки Иногда объявления двух функций внешне отличаются, но фактически совпадают.
Рассмотрим в качестве примера следующие объявления. чоьг) б(1пс "р); иоьг) х(ьпс р[]); // Ошибка, выражения *р и р[) эквивалентны Следует помнить, что компилятор не различает выражения *р и р[). Слсловательно, хотя внешне два прототипа функции Е различаются, на самом деле онн полностью совпадают. Перегрузка конструкторов Конструкторы можно перегружать. Фактически их-то и псрсгружают чаще всего.
Для перегрузки конструктора существуют три причины: гибкость, возможность создания инициализированных (неинициализированных) объектов и конструкторов копирования. В этом разделе мы рассмотрим только первые две причины. Конструктор копирования описывается в следуюшслг разделе. Перегрузка конструктора для достижения гибкости Довольно часто объекты класса можно создать несколькими способами. Для каждого из этих способов можно определить отдельный вариант перегруженного конструктора.
Эти варианты исчерпывают все возможности создать объект — при попытке сделать это непредусмотренным способом компилятор не найдет подходящего конструктора и выдаст сообщение об ошибке. Г)срегружснные конструкторы намного повышают гибкость класса. Они позволяют пользователю выбирать оптимальный способ создания объекта. Рассмотрим программу, создающую класс йаее для хранения календарной датьь Обратите внимание на то, что конструктор перегружен дважды. | аьпс1иде <ьовехеаы> Зьпс1ибе ссвс/)ьо> ивьпд паыеврасе эег)г Глава 14.
Перегрузка функций, конструкторы копироааюе и аргументы по умолчанию 36$ с1авв йасе ( зпс дау, топЕЬ, уеаез рц? ?вс даве(снах "д)з йаее(ьпс ю, з.пг й, зпе у)з цо1д виси даве()з // Инициализация строкой. йасезздаее(сиаг *д1 ввсапе(д, "%де*сед%*сад", аиопен, адау, ауеат)з // Инициализация цезвзми числами. дасез:даве(?пс т, зпс д, зп?. у) ( дау = дз поп?Ь = ви уеаг = у; ео1й йаееззвиои даве() соие « попе)з « "/" « дауз соне « "/" « уеат сс "1п"; ьпе таз.п() ( даве оЬ1(12, 4, 2001), оЬ2("10/22/2001")з оЬ?.в?зои даве(); оЬ2.вьои даве(); лесцхп 0? ) В этой программе объект класса даве можно инициализировать двумя способами: задав месяц, день и год в виде трех целых чисел либо в виде строки взлз/<Ы/зууу. Оба способа применяются довольно часто, поэтому имеет смысл предусмотреть два разных конструктора для создания объектов класса йвее.
Этот пример иллюстрирует основную идею, лежашую в основе перегруженных конструкторов: онн позволяют выбирать способ создания обьектов, лучше всех соответствующий конкретной ситуации. Например, пользователь может ввести дату в виде массива в. Эту строку можно сразу использовать для создания объекта класса даве. Для этого совершенно не требуется преобразовывать ее в другой вид. Однако, если бы конструктор даве() не был бы перегружен, строку в пришлось бы разбить на три целых числа.
з.пг. взаъп() ( спал в(80)з соцс « "Введите новую дату: с?п » в; даве д(в); д.в?зои даве(); Часть!). ((зык С~+ хеспхп О; з В другой ситуации пользователю удобнее инициализировать объект класса т?аее тремя целыми числами. Например, если дата является результатом неких вычислений, более естественно созданать обьект класса т)аее с помощью конструктора т?аее(зпе, 1пе.
1пе). Итак, в каждом конкретном случае существует оптимальный вариант. Перегруженный конструктор обеспечивает необходимую гибкость класса, особенно необходимую при создании библиотек. Создание инициализированных и неинициализированных объектов Перегруженные конструкторы часто используются для создания инициализированных и неинициализированных объектон (точнее, инициализированных по умолчанию).