Дж. Рамбо, М. Блаха - UML 2.0 - Объектно-ориентированное моделирование и разработка (1158633), страница 95
Текст из файла (страница 95)
~ача не допускает определение функций вне классов, но такие функции часто эмулируются во вспомогательных библиотечных классах, содержащих группы статических методов. Некоторые библиотечные классы )ата, такие как 1пгейег и Сойесйопз, полностью или почти полностью состоят из статических методов. Поскольку статические члены и экземпляры классов создаются отдельно от экземпляров объектов, инициализация их также происходит независимо. Статические члены в С++ объявляются внутри классов, но определяются и инициализируются вне их, тогда как в)ака статические поля люжно инициализировать как обычные поля или внутри статического инициализирующего блока. Статические члены гарантированно инициализируются перед использованием в программе, но взаимный порядок инициализации этих членов не определен. 396 Глава 18 ° Объектно-ориентированные языки 18.4.3.
Уничтожение объекта Если объект больше не нужен, его можно уничтожить, а память, которую он занимал, вернуть в пул. Статически выделенные объекты уничтожаются при выходе точки выполнения за границы программного блока, Идентификатор уничтоженного таким образом объекта использовать больше нельзя, потому что это будет ошибкой, — все равно, что позвонить по старому телефону человеку, который переехал. Срок существования динамически выделенных объектов потенциально может быть неограниченным, поэтому необходимо отслеживать те объекты, которые больше не нужны или существование которых перестает быть корректным, уничтожать их и освобождать занимаемую память. Для этого в С++ и )ача предусмотрены разные стратегии. В С++ программист несет ответственность за явное удаление объектов.
В)ата система сама отслеживает неиспользуемые объекты и удаляет их. Второй подход называется сборкой мусора (яагЬаяе сойесгюп) и реализуется через подсчет количества ссылок на объект. Когда ссылки заканчиваются (идентификаторов объекта больше нет), система помечает объект как подлежащий уничтожению. Периодически запускается сборщик мусора, который освобождает память, занимаемую всеми помеченными объектами, и возвращает ее в системный пул. Удаление объектов вручную в С++ создает дополнительную нагрузку на программиста, но зато дает возможность жестко контролировать жизненный цикл объекта и полностью моделировать события, происходящие с объектом, включая завершение его существования. Сборка мусора освобождает программиста от заботы о памяти, но ограничивает его контроль над завершением жизненного цикла.
В классах С++ могут быть определены деструкторы ())езггиссогз), аналогичные конструкторам. Они запускаются автоматически при уничтожении объекта. Деструктор выглядит как конструктор без аргументов, но перед именем класса ставится символ -, как в следующем примере: Хх-Хо (...). Деструкторы никогда не принимают аргументов и не возвращают никаких значений. Обычно в деструкторе выполняются действия, обратные действиям конструктора. Чаше всего к ним относится удаление динамически созданных членов класса, а также увеличение или уменьшение каких-либо счетчиков, освобождение ресурсов и т. д.
Деструкторы могут вызывать определенное поведение, которое должно быть осуществлено в конце жизненного цикла объекта. нтпдон :: нгпдонв )) ) // стирание окна и прорисовка скрытой ии осласти ) Процесс уничтожения противоположен процессу создания: сначала выполняется код деструктора, а затем уничтожаются требующие удаления члены класса (начиная с их деструкторов), после чего вся освобожденная память возвращается на кучу. 18.4.
Реализация функциональности 397 Удаление динамически созданного объекта осуществляется оператором пе]еге. Пустые квадратные скобки позволяют отличить удаление отдельных элементов массива от удаления массива в целом. с1авв Х ] . . . ] Х х1 = пее Х; Х *х2 = пех Х]20]; с]е1есе х1; с]е1есе [] х2; После удаления объекта С++ рекомендуется сразу же присвоить нулевые значения всем указателям, которые были с ним связаны.
Операция удаления, случайно примененная к нулевому указателю, не вызовет сбоя программы, тогда как повторное удаление объекта приводит к непредсказуемым результатам. Объекты )ача не могут быть удалены программистом вручную. Программист может попытаться инициировать уничтожение объекта, установив все ссылки на него равными нулю, и даже может порекомендовать системе выполнить сборку мусора, но гарантировать, что уничтожение будет выполнено в определенный момент, он не может. )ача позволяет классам перекрывать метод)гпайге(), определенный в классе ОЬ)есп Этот метод аналогичен деструкторам С++, однако существенное отличие состоит в том, что невозможно предсказать, в какой момент этот метод будет вызван системой.
18.4.4. Создание связи Взаимодействие объектов друг с другом приводит к созданию и уничтожению связей между ними. Такие связи должны создаваться во время выполнения поведения (метода), которое устанавливает ассоциацию между объектами, и удаляться во время выполнения другого поведения, которое эту ассоциацию разрушает. Следует избегать методов, осуществляющих непосредственное присваивание, а вместо них определять операции, скрывающие данные и устанавливающие связи только при выполнении определенных условий. Для установки связи, соответствующей односторонней ассоциации, объект запоминает идентификатор другого объекта, являющегося параметром операции.
Двусторонние связи могут быть созданы путем обмена идентификаторами, однако обычно рекомендуется инициировать обмен с одной стороны и инкапсулировать данные на другом конце, чтобы обеспечить непротиворечивую логику и полное обновление связей. Выбор класса, управляющего обменом, определяется логикой приложения. В приведенном ниже упрощенном примере на )ача студенты (5гипепа) хранят список текущих курсов лекций (Сои]зез), а для каждого курса хранится список студентов.
Поскольку решение прослушать курс лекций принимается студентом, а выполнение этого решения зависит от статуса студента, создание связи управляется методом 5гц1(еппасЫС]пы(Соигзе). Этот метод вызывает Соигзе.ептоИ(5ги])епг), который доступен классу 5йи(епг благодаря пакетному уровню доступа. Этот 398 Глава 18 ° Объектно-ориентированные языки уровень доступа предотврашает открытый доступ к клиентам (к классу Елго(- !тел/АррНсат(ол), и, таким образом, создание связи может выполняться единственным способом, описанным выше.
// файл Соигве.?ана рассаое зсьоо1; риЬ11с с1азв Соигве ( рггчаге Бггспи С1С1е; ргьнасе назьзес зсибепсв = пен навь5ес() риЬ11с Соигве (Бггспо пш) ( С1С1е пш) ) риЬ11с Бггспо соигвенаше() ( гегигп С111е1 ) Ьоо1еап епго11(згибепг вги) ( // проверка наличия свободных мест на курсе и т.д.
// в случае положительного ответа возвращается результат // метода Навьзег.абб гегигп згибепгв.абб(зги)! ) риЫ1с чо1б рггпСС1авзвьзс() ( Бувгеш.оиг.рггпг1п("С1авв Ььвг гог " + соигзенаше() + ":") 1Сегагог 1С = вгибепов.1СегаСог(); нЫ1е (1с.ьазнехс()) Бузсеш. оис. рг1пс1п ( ( (Бсибепс) 1с. пехс () ) .
всибепснаше () ) ) ) // файл Бсибепс.)ана раскаде всьоо1; риЫ1с с1авв Бгибепг ( рггчасе Бсг1пс паше( рг1часе Назьзег с1аззев = пеи Назьзег()~ риь11с Бсибепс(5сг1пн пш) ( паше = пш( ! риЬ11с Бгг1пя зсибепснаше() ( гегигп паше; ] риЫ1с Ьоо1еап аббС1авз(Соигзе сгз) ( // проверка доступности курса студенту, в случае положительного // ответа запрашивается добавление студента на курс у класса Соигве, // а потом курс добавляется в список гесигп ( сгз.епго11(сыз)) ? с1азвез.абб(сгв) : та1зе( ) риЫ1с чогб рггпССоигзез() ( 5узсеш.оис.рг1пс1п("соигзез тот " ь зсибепснаше() 1сегасог 1с = с1азвез.гсегасог( ньг1е (1С.ЬазнехС()) БувСеш.оио.рг1пС1п(((Соигве)гг.пехг()).соигвенаше()); ) ) // файл Кпго11шепгйрр11саг1оп.)ача 1шрогг 1оса1.вспоо1.* 18.4.
Реализация функциональности 399 риЬ11с с1аяя япго11щепГАрр1гсаггоп ( риъ11с зсас1с чо1б ща1п(5яггпЧ [) агяя) ( ягибепг щгке = пен ягибепг("щ1ке"): Яяибепг Ь111 пен Ясибепя("Ьг11"); Соигяе СГ = пен Соигяе("Туре Тьеогу") щ1ке.Аббс1аяя(гг): Ьг11.Аббс1аяя(ГГ); ГГ.РггпГС1аяяъ1яс() щгке.рггпгсоигяея() ) ) Если на момент создания объекта известно, с какими объектами он будет взаимодействовать, связи можно установить сразу же. Достаточно часто создание объекта должно зависеть от возможности установления свя:кй.
В этом случае конструирование объекта следует делегировать специальному методу, который будет проверять необходимые условия перед созданием объекта, потому что конструкторы ) ауа и С++ не могут возврашать ошибку или прерывать процесс создания. Средством для создания объектов может быть специальный класс или статический метод (см. раздел 18.4.2). В приведенном ниже примере на С++ объект Ттапзасг[оп (Транзакция) не будет создан до тех пор, пока не будет проверен номер счета и получен идентификатор этого счета (с которым устанавливается связь). с1аяя Тгапяассяоп ( ргосесгеб: // закрытый или защищенный конструктор, наличие которого исключает // возможность создания объекта извне вызовом его конструктора риь11с: ягаг1с Тгапяасс1оп* НакеТгапяасс1оп (попас сьаг* ассспищЬег) [ Ассоипс* ассс; // возврат нулевого указателя показывает, что транзакиня // запрещена 11 ( /* счет не в порядке */ ) гегигп 0; // возврат транзакиии для корректного счета гегигп пен тгапвассгоп(*ассг)! 18.4.5.