Главная » Просмотр файлов » лекции (2003) (Глазкова)

лекции (2003) (Глазкова) (1160821), страница 23

Файл №1160821 лекции (2003) (Глазкова) (лекции (2003) (Глазкова)) 23 страницалекции (2003) (Глазкова) (1160821) страница 232019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

Язык С++ справедливо ругают за то, что доступ к статическим членам возможен двоякий.

Пример:

class X {

...

static int j;

statiс void g();

};

………

X а,b;

Тогда можно обращаться:

      • к j – a.j либо X::j

      • к g() – a.g() либо X::g()

Форма записи a.g() не отражает сути, т.к. заставляет считать, что g() – функция - член класса, но в отличие от обычных функций this ей не передаётся. Поэтому более естественная форма обращения - X::g().

В языках Java и С# форма обращения через имя класса является единственно допустимой.

Лекция 17

Продолжим рассмотрение вопросов, связанных с понятием класса. Мы говорим, что классы проявляют дуализм: с одной стороны, это типы, а с другой – модули. В первую очередь класс – это тип данных. На прошлой лекции мы обсуждали понятие статических и нестатических членов. Синтаксис объявления статического члена:

static объявление_члена

Пример: (Java)

class X{

static int i;

...

}

Если в языках С#, Java static int i; – это и объявление, и определение (это языки без разделения определения и реализации), то в языке С++ это только объявление, которое говорит, что в классе X существует статический объект целого типа (но это только объявление, но не определение). В С++ в таком примере на этапе загрузки редактор связей выдает сообщение об ошибке: неопределенная внешняя ссылка. Решение этой проблемы в языке С++:

int X ::i;// это размещение переменной в памяти.

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

  1. инициализация /уничтожение объектов данных;

  2. проблема копирования;

  3. проблема преобразования типов данных.

Все эти проблемы так или иначе решаются с помощью специальных функций – членов классов. Про них компилятор знает нечто большее, чем про обычные функции: к этим функциям привязаны определённые стандартные действия. Все специальные функции обладают, с одной стороны, пользовательской семантикой; с другой стороны – системной.

Проблема инициализации/разрушения

Работать со сложными объектами можно, только если они инициализированы. Например, пусть стек реализован в виде линейной структуры: массив и переменная tор, которая даёт индекс первого пустого элемента в стеке (индекс верхушки стека). Даже такая простая структура данных должна быть инициализирована (например, tор=0;). Т.е. даже простые структуры данных надо адекватно инициализировать. В большинстве ЯП эта проблема не решается никак.

Например, в случае Modula 2 мы описываем S:Stack; но мы должны не забыть выполнить Init(S, 50).

С проблемой инициализации связана проблема уничтожения. В процессе своего функционирования объект может захватывать системные ресурсы. Наиболее часто используемый системный ресурс – динамическая память. Если язык без автоматической сборки мусора, то захваченные ресурсы надо явно освободить. Например, стек может быть переменной длины. Сама запись стек тривиальная: поле top и указатель на массив членов. Когда стек прекращает существовать, надо сделать Destroy(S); чтобы освободить выделенную Init() память.

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

Понятие конструктора, которое впервые появилось в языке С++, и потом пошло во все остальные языки, пытается решить эту проблему.

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

В частности, одно из важных событий в жизни объекта – это инициализация. Хотелось бы, чтобы объект был инициализирован в тот момент, когда он создаётся (тем самым гарантируется то, чтобы мы не можем работать с неинициализированным объектом).

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

Пример: type Stack is record

body is array (1...N)of integer;

top:integer:=1;

end record;

Теперь везде, где размещается переменная типа Stack (например, S: Stack) происходит инициализация.

Можно параметризовывать записи.

Пример: type Stack (N: integer) is record

body is array (1...N) of integer;

top : integer := 1;

end record

Теперь

S: Stark;|| ошибка

Надо писать

S: Stark(50); // отводится память по 50 элементов

В некотором смысле, это зачаточный вариант конструктора.

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

Обратим внимание, что действия, которые мы можем предпринять при инициализации объекта, сводятся либо к распределению памяти под массив, либо к инициализации простыми константными выражениями, либо выражениями, которые зависят от параметра соответствующей записи. Понятно, что легко придумать варианты, когда ни тот, ни другой случай не проходит. Например, если мы хотим сделать стек в виде массива переменной длины, но с динамичной памятью. Т.е. возможности инициализации объектов не очень широки. Более того, если стек представить в виде линейного списка, то инициализация тривиальна (она просто сводится к обнулению указателя S:=NULL;), но разрушение объекта нетривиально (необходимо выбросить все элементы стека из динамической памяти) – и здесь никакого механизма не предусмотрено.

Концепция конструктора и деструктора: это специальные функции, которые связаны с классом; конструктор вызывается в тот момент, когда объект размещается в памяти, а деструктор вызывается в тот момент, когда объект прекращает своё существование. Вообще, понятие специальных функций не сводится только к конструкторам и деструкторам.

Начнём обсуждение специальных функций и проблем, которые они решают. В языке С++ концепция специальных функций наиболее развита. В других языках (Delphi, C#, Java) специальные функции тоже есть, но их область применения поменьше.

Конструкторы и деструкторы в С++

classХ{

Х();// конструктор – это функция, которая одноименна с соответствующим классом

~Х();// деструктор: ~ имя класса ();

...

}

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

Вспомним понятие класс памяти.

Память бывает:

  • статическая,

  • квазистатическая (стековая),

  • динамическая

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

Язык С++ не позволяет управлять порядком инициализации статических объектов. Когда может быть необходимо управлять порядком инициализации статических объектов?

Рассмотрим стандартную библиотеку ввода/вывода в С++ - iostream.

В этой библиотеке есть стандартные потоки: cin,cout,cerr. При инициализации объектов могут возникать ошибочные ситуации.

Пример

Х(){

...

cerr<<“error…”

}

Пусть есть статический объект класса X; для него вызывается конструктор, причём до начала функции main. Этот конструктор ссылается на какой-то другой. Очевидно, cerr – это переменная, которая является статической (размещена на верхнем уровне). Очевидно, что этот канал вывода должен быть открыт. Естественно, что открытие этого канала происходит в конструкторе соответствующего объекта. Возникает вопрос: в каком порядке вызываются конструкторы статических объектов? Порядок этот в С++ никак не регулируется, и нет средств его регулировать, и поэтому мы не знаем, когда будет выполняться конструктор соответствующего объекта (до инициализации стандартной библиотеки ввода-вывода или после). Поэтому иногда может быть ошибка. Отметим, что в современных реализациях стандартной библиотеки такой ошибки не будет. За счёт чего? За счёт того, что там существует глобальная статическая переменная. Объектный файл делится на следующие части:

сегмент кода (СS),

сегмент инициализированных данных,

сегмент неинициализированных данных.

Статические переменные можно инициализировать на этапе загрузки (т.е. вообще до выполнения любого кода), поэтому можно контролировать, прошла ли инициализация, если нет – ее надо немедленно выполнить при обращении к функциям-членам соответствующего класса.

В общем случае, отсутствие механизма управления порядком инициализации статических переменных – это недостаток, и в более современных языках он исправлен.

Для статических объектов конструкторы вызываются до функции main (т.е. в стандартном прологе), а деструкторы вызываются в стандартном эпилоге.

Для квазистатических объектов конструктор работает в тот момент, когда управление проходит через объявление этого объекта. Неслучайно в языке С++ отсутствует разграничение между объявлениями и операторами в том смысле, что теперь любое объявление класса может рассматриваться как оператор (потому что, когда управление проходит через объявление объекта работает конструктор). Деструктор квазистатических объектов выполняется в момент выхода из блока (либо нормальным образом, либо с помощью оператора return, либо exit(); либо выход из блока по исключительной ситуации).

Динамические объекты

В языке С++ есть два специальных оператора nеw и delete.

Когда выполняется new X,

  1. работает менеджер динамической памяти, который отводит кусок памяти;

  2. работает конструктор который инициализирует этот кусок памяти

Когда выполняется delete:

  1. проработает деструктор, который превращает объект в кусок памяти,

  2. менеджер динамической памяти утилизирует оставшийся кусок.

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

Заметим, что конструкторы – это, с одной стороны, специальные функции, а, с другой стороны, – обычные функции класса. Конструкторы могут иметь и параметры. В зависимости от своего назначения в С++ выделяются следующие виды конструкторов:

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

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

  • конструктор преобразования,

  • все остальные.

Смысл этого деления в том, что специальные функции обладают особой семантикой, отличающей их от других функций, и которую знает компилятор. Очевидно, у каждого из этих трех видов конструкторов, по сравнению с общей семантикой (что конструктор вызывается, когда объект начинает существовать), есть и своя особая семантика. Заметим, что из названия конструкторов видно, что все три проблемы (проблема инициализации, проблема копирования объекта и проблема преобразования) с помощью конструкторов могут решаться. Конструктор умолчания – это конструктор вида Х(), т.е. не параметрический конструктор. Конструктор копирования – это конструктор вида Х(Х&) или Х(const Х&), т.е. который имеет один аргумент – ссылку на этот же объект. Конструктор преобразования имеет вид либо Х(Т), либо Х(Х&), либо Х(const T&), где Т – любой другой ТД, не совпадающий с Х. Все остальные конструкторы особой семантики не имеют.

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

Конструкторы умолчания вызываются тогда, когда нет явной информации, какой именно конструктор надо вызвать. Например,

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

Для динамического объекта Х р = new Х; // здесь также вызывается конструктор умолчания.

Как указывать параметры конструктора?

При объявлении переменной можно в скобках явно указывать параметры конструктора, например, Х х(1,0), это значит, что вызывается конструктор класса с профилем Х(int, int); ). Обратим внимание, что для динамического объекта Х * р = new Х(1,0); работает ещё одна концепция – перекрытия операций. Все конструкторы класса имеют одно и то же имя, совпадающее с именем класса, но разные профиль параметров. И компилятор по профилю параметров точно знает, какой конструктор вызвать. А если компилятор не видит никакого профиля параметров, он вызывает конструктор умолчания.

В каких контекстах может встречаться объявление Х х? Оно может появиться в файле на верхнем уровне (Х х; - такие переменные называются статическими, вызывается конструктор умолчания в стандартном прологе до начала функции main(); в блоке

( {...X x;...} – работает конструктор умолчания, но в тот момент, когда управление входит в блок); в классе (class Y{...X x;...} - это подобъект класса).

Объекты данных могут быть:

  • статические;

  • квазистатические;

  • динамические;

  • подобъекты другого ОД;

  • базовыми объектами.

У каждого конструктора есть своя нетривиальная системная семантика, которая состоит в инициализации базового класса и подобъектов. Пример: class Y: publicX{..}

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

Тип файла
Документ
Размер
825 Kb
Тип материала
Высшее учебное заведение

Список файлов лекций

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