Лекция 12 (Лекции (2009) (Саша Федорова))

2019-09-19СтудИзба

Описание файла

Файл "Лекция 12" внутри архива находится в папке "Лекции (2009) (Саша Федорова)". Документ из архива "Лекции (2009) (Саша Федорова)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "Лекция 12"

Текст из документа "Лекция 12"

13


Лекция 12.

Специальные функции

  • Конструктор

  • Деструктор

  • Оператор преобразования

  • Дополнительный возможности механизма классов

Важнейший класс специальных функций – конструктор.

Мы уже знаем, вызов любого конструктора происхдит , когда объекты отводится память. В языках с референциальной моделью в момент вызова конструктора происходит ссылки с объектом.

В С++, как мы знаем, объекты создаются при помощи конструктора. В других языказ за вопросы инициализации, копирования и удаления объекта также овечают именно специальные функции.

КОНСТРУКТОРЫ

Виды конструктора:

  • Конструктор умолчания(есть в C#, Java, C++, нету в Delphi).

  • Конструктор копирования(вызывается, когда происходит копирование объектов)

  • Конструктор преобразования(в С++, C#, Java конструктор не наследуется)

  • Иные конструкторы

Почему конструктор умолчания выделяется в особый класс? В чем его особенность?

В некоторых случаях объект создается автоматически. В Delphi генерации конструкторов нет, все объекты являются наследниками одного объекта, у которого уже есть конструктор.

В Java, C# и Delphi есть дерево объектов, и все объекты, созданные программистом, «торчат» из класса Object(C#). В классе Object есть конструктор Create() и деструктор Destroy(), из чего следует, что каждый объект в Delphi имеет хотя бы один конструктор и хотя бы один деструктор.

В С++ автоматически могут генерироваться конструктор умолчания и конструктор копирования.

Конструктор умолчания

Х а; //подразумевается вызов конструктора по умолчанию

X a(1); //явный вызова конструктора

X a(); //нельзя

А в случае с указателями можно двумя способами:

X * px = new X;

X * px = new X(); //В C# и Java можно только так

Существует еще 2 ситуации, котгда конструктор умолчания вызывается автоматически:

  • Наследование: конструктор умолчания для базового и производного классов

class X {

X();

X (int);

};

class Y: public X{

Y(); //если его нет, то явно сгенерируется конструктор умолчания(вначале перед ним, естественно, каждый раз будет вызываться конструктор класса Х.)

Z z;

};

Представим, что в класса Х конструктора нет. Возникают 2 вопроса:

  1. как вызывается конструктор базового класса

  2. как вызывается конструктор подобъекта

Вызов любого конструктора состоит из двух фаз:

  1. вызов конструктора базовой части

  2. вызов конструктора подобъекта

В любой из этих фаз может присутствовать ползовательская часть(то, что программист указал явно)

Пример «явного написания» конструктора в общем случае:

Заголовок [инициализация] тело

Например:

Y(): X(); z() {……………}

Можно и так:

Y(int I, int j): X(i); z(j) {/* пользовательская часть */};- пользовательская часть может отсутствовать

В C# и Java по синтаксису разрешены инициализации объектов:

class X{

Z z = new Z();

int i=0;

//простые инициализации можно выполнять непосредственно в коде самого класса. Более того, если для С++ критичен вызов конструкторов подобъектов, то в C# и Java мы работает со ссылками, и всегда можем их доопределить. Если вызов тривиален, то мы, конечно, можжем определить все сразу.

Синтаксис С# напоминает синтаксис С++, но в нем присутствует ключевое слово base, возвращающее ссылку на объект базового класса:

Y(): base(0) {………….}

А в Java для подобных целей есть ключевое слово super(аналог base в C#)

Вызов конструктора базового класса в Java может быть только первым оператором тела конструктора:

Y()

{ super(1); ………………….. }

Если первый оператор отличен от вызова super, то компилятор автоматически вставляет super();//вызов конструктора умолчания базового класса.

Замечание. В Ада для конструктора и деструктора использовались функции Init() и Destroy(). Для определения собственного конструктора и деструктора достаточно было переопределить эти функции(что, кстати, чатсо забывали делать, и это служило причиной многих ошибок)

Конструктор копирования

В С++ возможно несколько контекстов копирования:

  • передача параметров по значению

void f(X a); // передача фактического параметра функции по значению

X g() { return X(); }

  • «Инициализация присваиванием»

X a=b;//синтаксический сахар. Аналог строчкой ниже:

X a(b);

int a=-1;//Внимание! Это инициализация, а не присваивание!

Особенно это важно для статических объектов.

Следует заметить, что при переопределении оператора присваивания нам надо «освобождать» предыдущие ресурсы перед копированием, чего не надо делать в конструкторе коопирования.

Как мы помним, существует 2 семантики копирования:

глубокое и поверхностное(Deep/Shallow), поверхностное – побитовое, или неглубокое(если копируется ссылка – в C#, Java, Delphi, где бъекты имеют ссылочную природу). Поверхностное копирование линейного списка – это копирование ссылок на первый его элемент. В языках со ссылочной природой копирование по определению поверхностное: вот, например, в таком случае:

int [ ]a;

int [ ]b.

a = new int [N];

b=a;

Итак, проблем в копировании:

  1. Могут быть с поверхностным копированием

  2. В том, что копирование не всегда хорошо разрешать(и поверхностное, и глубокое – всегда могут присутствовать данные, доступ к которым лучше запретить.)

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

(1) X(X&);

(2) operator=(X&)

Если мы не копируем объект, то конструкции (1) и (2) не нужны. Описав прототип этих функций, но не определив их, мы запрещаем копировать объект данного класса. Когда отсутствует и прототип, и объявление, конструктор копирования генерируется автоматически.

Минимум объект может иметь один конструктор: конструктор копирования.

Конструктор копирование генерируется так:

Если класс верхнего уровня, конструктор генериурется почленно: для каждого члена объекта:

class X{

int a;

Z z;

};

class X{

X();

X(X&);

};

class Y: public X{

//как будет сгенерирован конструктор и какой конструктор он будет вызывать?

Если ничего не написать:

Генерируется конструктор копирования с учетом конструктора копирования базового класса.

А если написать: Y(Y&){………………}, то перед {………………}, очевидно, вызовется конструктор умолчания базового класса.

Если нас устраивает стандартная семантика копирования по умолчаию, можно ничего не писать...

Мораль: в инициализаторе конструктора копирования производного класса надо написать конструктор копирования. «Ручками».

Y(Y& ): X(y){……………….}

Эта же проблема присутствует и в других языках.

С#

В классе Object(общего предка для всех классов), есть защищенный метод MemberwiseClone, возвращающий копию объекта.

Java

В этой точки зрения наиболее адекватно проблема решена в Javа. Там существует 4 уровня поддержки копирования.

Интерфейс-маркер – по определению пустой интерфейс(не содержит членов).

Интерфейс – это просто набор методов. Он определяет некий контракт, говорящий о том, что если класс поддерживает некий интерфейс, он должен реализовывать определенный набор методов. А если интерфейс пустой, то все его члены-методы «зашиты» в компилятор.

Интерфейс называется сloneable, когда он пустой.

В Java был введен пустой интерфейс cloneable, содержащий метод Clone(), осуществляющий побитовое поверхностное копирование. Возможны 4 ситуации:

  • Полная поддержка копирования – возможность явной реализации. Класс X реализует интерфейс Cloneable:

Сlass X: Cloneable{

//Тут мы должны написать:

public X Clone();

//Допускается также:

public Object Clone();

..........................................

Метод Clone() может использовать любые члены класса(и приватные тоже.)

};

  • Возможна и другая ситуация: полный запрет кпированияя: при поопытке скопировать объект выбрасываем исключение. Подменяем соответсвующий защищенный метод clone():

class X{

protected Object Clone(){ throw CloneNotSupportedException; }

………………………………….

};

  • Условная поддержка: элементы, которые копируются, могут быть под полным запретом.

Пример: коллекция умеет себя копировать, а элементы, из которых она состоит – нет.

class X: Cloneable{

public X Clone throwing CloneNotSupportedException

{

//Для каждого элемента коллекции вызывается метод Clone();

};

…………………………………………………..

};

  • Еще одна ситуация – когда мы не наследуем метод Clone()

О статических членах

Как мы знаем, статические члены должны инициализироваться 11 раз. Но когда?

Рассмотрим статические члены класса в различных языках.

C++

class Z{

static X a;

…………..

};

X Z::a(…);

C#

Существует статический конструктор, который вызывается 1 раз до первого использования и до первого обращения к любым членам класса.

static X() {…………}; //полная форма статического конструктора по умолчанию в языке C#

Java

static{…………….}; //аналог статического конструктора в Java

Деструктор

Вообще говоря, к деструкторам применимы те же правила. Деструкторы ненаследуются, а, следовательно, будут сгенерированы автоматически.

Деструкторы начинают работать в начале уничтожения объектов.

Напомним - в C# и Java есть сборщик мусора. В С++ и Delphi сборщика мусора нет, потому возникает необходимость явного освобождения памяти.

C++

delete p;

Отличие С++ от Delphi – в нем происходит автоматический вызов деструктора.

Общая проблема - в процессе функционирования объекты получают некий ресурс.

В С++ и Delphi мы всегда контролируем, когда ресурсы освобождаются.

Специальные функции в Delphi:

X:=I.Create();

X.Create();

X.Free

В С# и Java за счет присутствия сборщика мусора момент уничтожения объектов невозожно отловить. Но иногда программа может кончиться раньше, чем сборщик заметит мусор

C# Пример

Класс Image

Статический метод FromFile

Image im=Image.FromFile(fname);

//обработка im

//изменение im

im.SaveToFile(filename);//файл захвачен. Будет освобожден только тогда когда уничтожится объект im.

Вот тут сборка мусора вредит! Мы не будем иметь доступа к захваченному файлу вплоть до момента, когда сборщик мусора уничтожит наш im.

O блоке try и finally а также о Dispose

В C#, Java, Delphi существует конструкция

try

блок

finally

{

………………..
}

Delphi:

try

операторы

finally

операторы

end

.Такая вещь, как finally, очень важна. Она будет выполнена независимо от того, как кончился блок.(Это необходимо, так как в C# и в Delphi нету вызова конструктора по умолчанию в конце блока)

В C# для решения подобных проблем необходим общий интерфейс IDisposable с методом Dispose(). Данный метод вызывает финализатор объекта и ставит его в очередь на уничтожение, обеспечивая выполнение деструктора.

Вот так:

try

{

//…….

}

finally

{

im.Dispose();
}

Вводится специальная конструкция:

using(инициализатор) //инициализатор – T x=expr; x=expr;

блок

Который эквивалентен

try{

инициализатор

}

finally{

x.Dispose();

}

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

Учитывая то, что в Java есть сборщик мусора, там не существует деструктора. В классе Object существует защищенный метод

protected void finalize();

который вызывается, когда объект перестает существовать. После вызова такого метода объъект становится недоступен.

Однако! Существуют методики, позволяющие возродить к жизни уже убитый объект. Конечно, это не самая лучшая техника и следует ее по возможности избегать.

В случае, если класс на протяжении своего существования должен освобождать ресурсы не один раз, он обязан содержать метод Close(), который будет это делать. Метод Dispose() вызывается один раз , а close должен быть запрограммирован таким образом, чтобы можно было вызывать его много раз.

В Java метод finalize() вызывается сборщиком мусора. В C# существует деструктор – тонкая обертка для финализзатора finalize().

Динамическая сборка мусора

Динамическая сборка мусора вызывает множество проблем. Простейший алгоритм сборки мусора – mark and sweep – алгоритм, основанный на подсчете числа ссылок на каждый объект. Как только это чсло становится равным нулю, объект уничтожается. Но в С# и Java возникает проблема кольцевых ссылок.

В любом случае, алгоритм сборки мусора должен делить объекты на «живые» и «мертвые».

Как работает сборщик мусора?

В программе у нас существуют

  • статические объекты классов

  • стек у main

Существует таблица ссылок на объекты. Помечаем все «живые» объекты(объекты верхнего уровня), а потом у них(внутри них) ищем другие ссылки, и таким образом рекурсивно обходим все. Получаем глобальную таблицу всех объектов. Все НЕживые объекты по определению есть мертвые. Уничтожаем их и радуемся

Замечание. Объект может быть подготовлен к уничтожению, но еще не уничтожен. Пример – работа с файлами. Пусть нам необходимо прочитать некоторый файл. Образ его уже подготовлен на цуничтожение, а данные еще остались. Возникает понятия сильной ссылки(ссылки на живой объект) и слабой ссылки(weak reference – ссылки на объект, подготовленный на уничтожение, но еще не уничтоженный).

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