Лекция 19 (лекции (2002)), страница 3

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

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

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

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

Текст 3 страницы из документа "Лекция 19"

x.P( );

Даже по синтаксису и в языке Оберон, и тем более в языках, в которых есть классы, виден только один объект, в зависимости от которого вызывается соответствующая процедура. В Аде может быть случай когда у процедуры есть 2 параметра, и оба параметра являются cw-типом. Для чего может пригодиться такое связывание? Рассмотрим пример с Figure. Для фигур в некоторых случаях очень полезна процедура вычисления пересечений InterSect, у которой есть 2 параметра Figure1, Figure2. Понятно, что абстрактный метод пересечения мы реализовать не может. Т.е. если речь идет о классовом языке

class Figure{

Figure & InterSect(Figure &);

}

У процедуры InterSect фактически будет 2 аргумента: Первый – тот самый указатель this, который передается InterSect. Второй – Figure &.

Figure

Point Line

Мы можем в иерархии классов для каждой фигуры переопределить кучу методов InterSect (для Point мы должны написать реализации метода InterSect для всевозможных фигур, также для Line мы должны переопределить метод InterSect для всех возможных типов). Допустим, что мы хотим вычислить для массива Figure * a[ ] пересечение всех фигур. Как для a[0] и a[1] сделать соответствующий вызов InterSect? Вся беда в том, что мы здесь должны знать конкретно какого типа a[0] и какого типа a[1], и вызывать метод InterSect от двух параметров уже в зависимости от их конкретных типов. Хотелось бы ввести такой механизм

Intersect(a[0], a[1]);

который бы динамически выбирал ту реализацию InterSect, которая соответствует динамическим типам a[0] и a[1]. На языках, в которых есть привязка к единственному типу объекта, подобного рода вещи смоделировать достаточно нелегко. В случае языка Ада у нас есть базовый тип Figure

type Figure is tagged record … end;

procedure InterSect(X1: Figure'class, X2: Figure'class);

Реализуем соответствующие процедуры InterSect.

InterSect(a, b);

Где а и b – 2 объекта типа Figure. Мы ничего не знаем о конкретном типе этих а и b, но будет автоматически выбрана нужная процедура InterSect. Если же ее нельзя выбрать, тогда будет выдано сообщение об ошибке. Естественным образом случай мультиметодов обобщается на любое количество классов. Это последствие достаточного хитрого механизма динамического связывания в языке.

В языке С++ можно было бы реализовать соответствующие мультиметоды, но для этого был необходим дополнительный синтаксис. Подробнее см. книгу Страуструпа "Дизайн и эволюция языка С++", который обсуждал альтернативы, как можно было бы в С++ реализовать мультиметоды. В настоящее время этого нет. Некоторые другие языки, которые мы сейчас не рассматриваем, например COS (Common Object System), также реализуют мультиметоды.

Последнее замечание, которое касается динамического связывания.

Динамическое связывание и множественное наследование.

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

X Y

virtual void f( ); virtual void g( );


Z

void f( );

void g( );

В классе Х определена виртуальная функция f, в классе Y – g. В классе Z обе эти функции переопределяются.

Z z;

X * p1; Y * p2;

p1= & z;

p2= & z;

Это можно сделать, т.к. от более широкого типа к более узкому типу присваивать можно. Вызываем функцию

p1->f( );

p1, p2

X

Y

Z


Должна быть вызвана функция f из Z потому, что раз она виртуальная, значит связывание должно быть динамическим.

p2->f( );

Никакая функция не будет вызвана. Компилятор выдаст сообщение об ошибке. Аналогичным образом ошибочна конструкция

p1->g( );

p2->g( );

Будет вызвана функция для Z. Функции для Z, которые мы пишем, прекрасно осведомлены о том, что у нас есть объекты класса Х, объекты класса Y и новые объекты класса Z. Представим, что функция g не переопределяется, а наследуется классом Z от класса Y.

p2->g( );

В общем случае компилятор не знает для какого типа будет вызвана функция. Он вызывает виртуальную функцию g (он даже не знает какую потому, что это зависит от динамического типа р2 (Z это или Y)). Функция g написана для класса Y, который о множественном наследовании ничего не знает. Когда мы пишем g, мы еще ничего не знаем о том, что может выводиться из Y. Объекты класса Y смещены относительно указателя p2. Получается, что механизм реализации должен быть следующим: Если функция g не перекрыта, на самом деле ей должен передаваться указатель на Y

p 1

p2 X

Y

Z

потому, что компилятор, программируя функцию, знает, что у него есть указатель with, и если

class Y{ int a, b}

то компилятор знает, что по нулевому смещению ссылка на таблицу виртуальных методов, по следующему смещению а, по следующему смещению b. Если функция g не переопределена в классе Z, и ей передается указатель на X, то все смещения будут не верны. Т.е. в случае множественного наследования механизм вызова виртуального метода должен носить несколько другой характер. На самом деле так оно и есть. Проблем с функциями из первого класса (X) никогда не будет потому, что и в случае единичного наследования, и в случае множественного наследования он стоит в начале. В случае Z тоже проблем нет, поскольку компилятор знает, как выглядит полный объект Z. Но при вызове виртуальных функций для промежуточных классов в цепочке множественного наследования возникают проблемы. Поэтому в ТВМ надо хранить адрес функции и смещение d, которое нужно прибавлять к указателю.

ТВМ

X

& f 0


Y

a & g d

b

Z

& f 0

& g 0

Для X (для первого класса) d всегда равно 0. Особенно неприятно то, о чем говорил Страуструп, что не хорошо заставлять платить пользователя за конструкции, которыми он не пользуется. В этом случае с точки зрения накладных расходов и по памяти, и по времени реализация усложняется. Если программист не использует множественное наследование, он все равно должен платить за то, что кто-то его может использовать. Поэтому естественным выходом будет сделать для множественного наследования одну реализацию, для единичного наследования – другую. Но это существенно усложняет язык. Проблемы при множественном наследовании происходят, когда идет множественное наследование по данным. Если бы в классах X иY никаких данных не было бы, тогда никаких проблем с функциями f и g тоже не было бы, и можно было бы обойтись одной таблицей. Проблемы при реализации возникают только в том случае, когда наследуются данные у нескольких классов. Не случайно в C# и Java множественное наследование есть, но только по данным идет единичное наследование, а от классов, в которых нет данных (интерфейсы), может идти обычное множественное наследование.

Глава 3. Абстрактные классы и интерфейсы.

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

Пример:

class Figure{

virtual void Draw( );

};

Из этого класса выводим новые.

Point

Figure Line

Circle

Очевидно, для каждого из этих классов мы пишем свою реализацию метода Draw. Но при перетрансляции программы загрузчик выдаст сообщение о том, что есть ссылка на функцию Draw для типа данных Figure, а самой функции нет. Метод Draw для Figure может вообще не вызываться, но компилятор сгенерирует ТВМ для класса Figure и заполнит ее ссылкой на метод Draw. Загрузчик не обнаружит эту функцию. Поэтому единственный вариант – написать эту функцию. Когда в Turbo Pascal впервые для фирмы Borland появились объектно-ориентированные свойства, там была специальная библиотечная процедура

Abstract( );

Это просто такой интеллигентный способ завершения подпрограмм. При вызове этой процедуры выдается сообщение, вроде: "Этот метод вызывать нельзя." и программа сваливается. Дело в том, что метод Draw вызывать действительно нельзя. Объект собственно класса Figure никакого смысла не имеет, он абстрактный. Figure имеет смысл только с точки зрения того, что из нее будут выведены какие-то новые конкретные классы, в которых виртуальные методы будут переопределены. Просто заводить данные типа Figure никакого смысла нет.

Figure C;

C.Draw( );

Сама по себе Figure никакого смысла не имеет, она имеет смысл только через указатели или ссылки, которые на самом деле будут ссылаться на объекты производных классов. Есть классы, которые вводятся только как вершина в иерархии сами по себе смысла не имеют. Чтобы запретить использование явным образом таких классов и введено понятие абстрактного класса, и связанного с ним понятия чистой виртуальной функции (это в терминологии языка С++). Чистая виртуальная функция – это функция, от которой не требуется никакой реализации. В данном случае мы должны были написать

class Figure{

virtual void Draw( ) = 0;

}

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