Главная » Просмотр файлов » И.Г. Головин, И.А. Волкова - Языки и методы программирования

И.Г. Головин, И.А. Волкова - Языки и методы программирования (1160773), страница 21

Файл №1160773 И.Г. Головин, И.А. Волкова - Языки и методы программирования (И.Г. Головин, И.А. Волкова - Языки и методы программирования) 21 страницаИ.Г. Головин, И.А. Волкова - Языки и методы программирования (1160773) страница 212019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 21)

Деструкторы и финализаторы —это специальные функции-члены класса, автоматически вызываемыепри уничтожении объекта класса. Роль деструкторов и финализаторов — освобождение захваченных объектом вычислительных ресур­сов. Если объект не захватывает ресурсы или ресурсы освобождаютсяавтоматически, то нужды в деструкторе нет.Деструктор класса X в языке C++ имеет вид~Х () ;Деструкторы бывают только без параметров.В языке Java деструкторов нет, их роль (до определенной степени)играет метод void finalize() — финализатор.В языке C# формально деструкторы есть (точнее есть функции,название и синтаксис которых совпадают с деструкторами C++),однако их поведение аналогично поведению метода finalize ()в языке Java, поэтому будем также называть их финализаторами.Деструкторы по смыслу обратны конструкторам, поэтому поведе­ние и порядок вызова деструкторов обратны поведению и порядкувызова конструкторов соответствующих объектов.

Так, например,в языке C++ момент вызова деструкторов обратен моменту вызоваконструкторов:1) деструкторы статических объектов вызываются после выходаиз функции main;2) деструкторы квазистатических объектов выполняются при вы­ходе из блока;3) деструкторы динамических объектов выполняются при вызовеоперации delete.Как уже отмечалось, в C++ существуют также временные объекты.По правилам языка они уничтожаются при выходе из конструкции,в контексте которой создаются. Например, временные объекты, соз­данные при выполнении вызова функции, уничтожаются (и вызыва­ется соответствующий деструктор) сразу после завершения вызова.Как и конструкторы, деструкторы имеют пользовательскую (телообъявленного деструктора) и системную (сгенерированный код) части.Системная часть выполняется после тела деструктора.

В системнуючасть входят вызовы деструкторов подобъектов (в порядке, обратномконструированию) и вызовы деструкторов базовых классов.101Если в классе не объявлен явный деструктор, то компилятор гене­рирует неявный деструктор класса, состоящий только из системнойчасти.Итак, программист на языке C++ может достаточно точно уста­новить момент вызова деструкторов объектов. На этом основанапростая и эффективная техника гарантированного освобождениялокально захваченных ресурсов, называемая «захват ресурса — этоинициализация» (английская аббревиатура — RAII).

В соответствиис этой техникой для работы с ресурсом разрабатывается класс, в кон­структоре которого происходит захват ресурса. Освобождение ресурсапроисходит в деструкторе объекта. Для работы с классом в текущемблоке объявляется локальная (в нашей терминологии квазистатическая) переменная, при создании которой происходит захват ресурса.Далее работаем с переменной, а после выхода из блока освобождениепроисходит автоматически.Многие классы из стандартной библиотеки поддерживают этутехнику, например классы ifstream и ofstream, представляющиесобой внешние файлы ввода и вывода.

В конструкторах этих клас­сов происходит открытие файла, в деструкторах — закрытие. Схемазадачи по обработке информации из внешнего файла может иметьследующий вид:{// текущий блокifstream in ("inputfile") ; // открыли вводofstream out ("outfile") ;// открыли вывод// обработали информацию из in// и скопировали в out} // при выходе из блока файлы автоматически// закрылисьПрограммист, использующий эту технику, гарантированно осво­бождает ресурсы.

Подробнее эта техника рассматривается в [17].Конечно, «утечка» ресурсов происходит и в программах на C++, нопроисходит она, как правило, в объектах из динамической памяти.В языках C# и Java вместо деструктора предлагается реализоватьметод-финализатор. Проблема состоит в том, что финализатор вы­зывается сборщиком мусора, поэтому предсказать момент вызовафинализатора невозможно.

Более того, возможна ситуация, когдапамяти хватает, и финализатор вообще не будет вызван. Поэтому дляклассов, захватывающих ресурсы, программист должен реализоватьобычные методы, которые освобождают эти ресурсы (например,метод close () для закрытия открытых файлов). На программистапользователя возлагается ответственность за своевременный вызовтаких методов.

Кроме того, необходимо предусмотреть вызов «очи­щающих» методов в финализаторе, если программист-пользовательпо каким-то причинам сам их не вызвал. Таким образом, наличияавтоматической сборки мусора недостаточно для написания на­102дежных программ, корректно работающих с вычислительнымиресурсами.Копирование объектов. По умолчанию языки предоставляютсредства для поверхностного копирования (иногда такое копированиеназывают побитовым).В языке C++ копирование объектов происходит при выполненииоперации присваивания и при инициализации объекта копированиемиз другого объекта такого же типа.

Первая ситуация очевидна, а вто­рая требует пояснений. При инициализации объекта класса всегдавызывается конструктор. В случае инициализации копированием вы­зывается специальный конструктор копирования, т. е. конструктор,имеющий прототип:X (const Х&), либо X (Х&)Таким образом, объект, из которого копируются данные, пере­дается в конструктор по ссылке.Конструктор копирования вызывается в следующих контекстах.1. Объявление объекта:Х а ; // работает конструктор умолчания Х()X b = а; // работает конструктор копирования Х(а)Заметим, что эта запись полностью эквивалентна следующейзаписи:X Ь(а); // работает конструктор копирования Х(а)2.

Передача параметра функции по значению (конструктор ра­ботает при инициализации формального параметра фактическимпараметром):void f (X а);X b;f (to) ; /* работает конструктор копирования Х(Ь)формального параметра а */для3. Возврат значения функции (конструктор работает при инициа­лизации временного объекта возвращаемым значением):X МакеХО{X а;return а;}X Ь;b = МакеХО; /* работает конструктор копированияX temp(а) для временного объекта, далее операцияприсваивания b = temp; */4. При возбуждении исключения типа X (см. гл.

9):103X а;throw а;Каждый класс имеет операцию присваивания и конструкторкопирования. Если в классе нет явно определенных операции при­сваивания и конструктора копирования, то они генерируются ком­пилятором. Сгенерированные компилятором присваивание и кон­структор копирования осуществляют поверхностное копирование.Генерация происходит почленно: для членов-данных базисных типовкопирование побитовое, для членов-подобъектов вызывается соот­ветствующая операция (конструктор копирования), которая можетбыть сгенерированной, а может быть и явной.Программист-разработчик класса сам определяет, какая семантикакопирования требуется для класса.

Если стандартное поверхностноекопирование не работает, то программист должен явно определитьв классе операцию присваивания и конструктор копирования.Заметим, что компилятор требует единого подхода к реализациикопирования: операция присваивания и конструктор копированиядолжны одновременно либо генерироваться, либо реализовыватьсяявно.Приведем пример простого класса, реализующего динамическийвектор (разумеется, это модельный пример, в реальной жизни следуетиспользовать векторы из стандартной библиотеки).

Вектор содержитв себе указатель на динамически размещаемый массив и требуетглубокого копирования:class Vector {int *body;int size;public:Vector (int sz){body = new int[size = sz];}Vector (const Vector & v){body = new int [size = v.size];for (int i = 0; i < size; i++)body[i] = v.body[i];}Vector Soperator = (const Vectors v){if (this != &v) {delete [] body;body = new int [S size = v.size];for (int i = 0; i < size; i++)body[i] = v.body[i];104}return *this;}-Vector() { delete [] body; }int& operator[] (int index) { returnbody[index]; }};Обратите внимание на реализацию операции присваивания,которая делает то же, что и конструктор копирования, но предва­рительно она должна «очистить» объект, при этом проверив, нет липрисваивания в себя.Попробуйте ответить на вопрос, что будет, если убрать явныеоперации присваивания и конструктор копирования, т.е.

оставитьстандартную семантику копирования.В языках C# и Java операция присваивания применяется к типамзначений и ссылкам. Поэтому понятий конструктора копированияи переопределения операции присваивания там нет. Для копирова­ния содержимого объекта следует определить метод класса Clone ()(в Java — clone ()), который возвращает ссылку на копию объекта.Реализация метода, конечно, должна учитывать семантику копиро­вания для объекта класса. Для реализации поверхностной семантикиязык Java предоставляет вариант метода clone () , реализующегопростое копирование всех членов-данных, а язык C# — методMemberwiseClone () с аналогичной семантикой.Преобразование объектов классов.

Для реализации явных пре­образований объектов классов вполне хватает средств, которые мыуже рассмотрели. Пусть X — это новый класс, а Т — произвольныйтип данных (отличный от X и необязательно класс). Тогда конструк­тор с прототипом X (Т) можно рассматривать как функцию явногопреобразования из типа т в класс X:ТXXbt;а = new X(t); // Java или C#b(t); // C++= X(t); // C++Аналогично нестатическая функция-член класса X с прото­типомТ МакеТоможет рассматриваться как функция явного преобразования изкласса X в тип т.Однако приведенные примеры таких преобразований явные, т.е.явно указанные программистом.При этом проблема состоит в возможности сделать неявны­ми преобразования, определяемые программистом (называемые105пользовательскими), т.

е. заставить компилятор вставлять вызовысоответствующих функций, как это происходит, например с преоб­разованиями арифметических типов в C++.Язык Java запрещает любые неявные преобразования междуобъектами классов (исключение составляют только неявные преоб­разования к стандартному типу string, разрешенные в некоторыхконтекстах).Языки C++ и C# разрешают неявные преобразования для классов,определяемых пользователем.В C++ преобразования определяются специальными функциямичленами: конструкторами преобразования и функциями преоб­разования.Конструктор преобразования имеет прототип видаХ(Т)(можно еще Х(Т&)и X (const Т&) )При наличии такого конструктора допустимо неявное преобра­зование из Т в X:Т t;X b(t); // это явный вызов конструктора!b = t; /* а вот это - уже неявное преобразование:транслятор вставляет такой код: b = X(t); */void f (X а);f(t); // еще неявное преобразование: f(X(t));void g(const X& a);g(t); // аналогично: g (X(t ));Заметим, что в процессе неявного преобразования могут появ­ляться временные объекты.Функция преобразования имеет видclass X {operator ТО;,};У функции преобразования нет типа возвращаемого значения (оноопределяется именем функции) и нет параметра (кроме неявногопараметра this).При наличии такой функции допустимы неявные преобразова­ния:X а;Т t;t = а; // t = a.operator Т();void f (Т t);f(a); // f(a.operator T ());void g(const T& t);g(a);106// g(a.operator T ());Неявные преобразования можно вызывать и явно, используяобычный синтаксис:Х а , b; Т t;а = (X )t ;t = (Т )b ;Ключевое слово e x p l i c i t .

Неявное преобразование, осущест­вляемое конструктором (преобразования), может иметь неприятноеследствие: иногда конструктор имеет синтаксис конструктора преоб­разования случайно, а само преобразование семантически бессмыс­ленно с точки зрения типа данных. Например, в рассмотренном ранееклассе Vector конструктор Vector (int) является конструкторомпреобразования, поэтому следующий пример вполне корректен, хотяособого смысла не имеет:Vector v (20);v = 1; // v = Vector (1); - скорее всего, ошибка// старое содержимое v уничтожено,// v заменен новым вектором длины 1Для подавления неявного вызова конструктора преобразования,если такое действие может привести к ошибке, конструктор преоб­разования необходимо объявлять с использованием ключевого словаe x p l i c i t (явный):explicit Vector (int sz) ;Теперь компилятор выдаст ошибку в приведенном примере.

Характеристики

Тип файла
PDF-файл
Размер
3,27 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6511
Авторов
на СтудИзбе
302
Средний доход
с одного платного файла
Обучение Подробнее