Языки программирования, 25 лекция (от 05 декабря)
Материал из ESyr's Wiki pages.
Предыдущая лекция | Следующая лекция
Содержание |
Динамическое связывание
Рассмотрим реализацию дин связывания на пример C++ и Smalltalk. В С++ наиболее простая и быстрая. В Smalltalk наиболее сложная и гибкая. Потом рассмотрим дан связ C#, Java, Delphi и Ada 95.
У на есть указатель или ссылка и в зависимости от динамического её типа, вызывается соотв функция. Когда мы видим ссылку, мы должны посмотреть на её статический тип. Потом посмотреть на профиль функции, то узнать виртуальная она или нет. Если она виртуальная, то объект может ссылаться на объект любого производного класса. В классе есть скрытое поле – указатель на таблицу вирт методов (ТВМ). По стандарту программисту она недоступна. Таблица состоит из адресов функций. Таблица вирт методов – структура которая поддерживается во время выполнения. Для производного типа T1, который замещает f и добаавляет h, таблица будет следующая, для T2 следующая:
T | T1 | T2 | |||
---|---|---|---|---|---|
&T::f | &T1::f | &T2::f | &T::g | &T::g | &T2::g |
&T1::h | &T2::h | ||||
&T2::W |
Ссылка на ТВМ сидит по нулевому смещению. Делать её или нет понятно по типу. Для любой таблицы и её производной известно, что f имеет определённое (нулевое) смещение. Для любого типа и для таблицы вирт типов накладные расходы одни и те же.
Накладные расходы: по указателю на объект и по таблице вирт методов на тип. Много или мало?
Если в классе есть хотя бы одна вирт функция, то можно объявлять их сколько угодно без дополн нагрузки. Например, деструктор тоже делают виртуальным.
Теперь когда говорим delete p то уничтожаем ту память, которая отведена.
Схема реализации в С++ очень эффективна.
Другой вариант реализации в Смаллток.
В СТ нелинейная организация памяти.
Там есть Object и у каждого класса есть ссылка на родителя.
Все поерации подводятся к x.f(y)
Всё на свете в Ст есть объекты, в том числе константы.
У каждого объекта ест ссылка на таблицу обработчкиов сообщений (message handling table, mht). Обработчики могут динамически добавляться и удаляться, но это делается не для объектов-экземпляров, а для классов.
У нас есть сылка на объект и просматриваем таблицу на предмет искомого обработчика. Если не нашли, идём в суперкласс.
В Си Компилятор создаёт объединённую таблицу методов, поэтому можно обойтись одной таблицей, причём там записи идут в порядке наследования.
В Ст мы не можем сказать, сколько времени понадобится на поиск. Ошибка не найденности метода возникает во время выполнения.
Тем не менее, эта реализация достаточно гибкая. Но для эффективного программирования не подходит.
Другие ЯП:
шар, джава, дельфи
Джава.
Все методы динамически связанные. Правда, еасть несколько тонкостей: с одной стороны это сущ упросщение. С другой, у нас есть
class X { final public void f() {...} ...
X x; x.f();
final - Даже если наследуесм X , не можем замещать f. Компилятор имеет право в некоторых случаях внимать виртуальность вызова. Если финальный класс, то все методы можно компилятору делать недин.
Если методы приватные, то они как бы становятся невидимыми:
class X { private void f() {} void g() { f() } - вызов должен быть виртуальный }
class Y extends X { publc voi f() {} - не замещение.
В конструкторе виртуальность вызовов снимаается
В Джаве приватные методы не нужны, и компилятор не ругается в том случае, если происход ит перепопределдение.
Вторая неприятность с пакетным доступом:
package P;
class X { void pac() {} public void g() {pac()} }
class Y extends X { void pac() {} }
Y y = new Y(); y.g();
вне пакета свяжется с pac y.pac внутри – y.pac
ашрп, дельфи
public virtual void f() {} public procedure F; virtual;
вирт функция может стать невирт
class Y : X { public void f() {} - ошибка. так как эта функция замещает виртуальную, но об этом ничего не сказано. правильно public override void f() {}
Если хочется ввести новый отсчёт виртуализации или развиртуалить, то нужно объявить ключевое слово new:
public new virtual void f() {}
Дельфи – если перегружаем, то overload
виртуальносить распространяется и на механизм свойств. Но нельзя гет объявить виртуальным, а сет нет.
//Механизм дин связывания отличается почти сахарными свойствами
Адское связывание
Приватные методы связываются статически, а пакетные
Ада-95
type T is tagged record ... end record; - тегированная запись procedure P (X:T); ...
P – является ли дин привязанной к типу т? зависит от того, как опишем функцию.
type T1 is new T with record ... end record; procedure P(X:T1);
A:T; B:T1; P(A); P(B);
определено понятие T class – новое для Ада 95
array(INdex ranged) of T
массив т и его сыновей.
CW-type
Class Wide type – типы-классы
Рассмотрим некоторую процедуру g
PROCEDURE G(X:T class) is ... P(X); end G;
если процедура описана...
у нас есть процедуры, у которых параметры – конкретные типы. Оба случая вызова тип класс, и вызов P будет динамическим.
Определяется набор функций P, и в зависимости от того,Ю что представляет собой дин тип X, то для него определно понтие дин типа. Статический тип у него Т, а дин – его.
A : T; B: T1;
G(A); G(B); - дин привязка
Мультиметод – метод, привязанный к неск типам. Пусть есть тегированный тип X, Z.
procedure P(A:X, B:Z)
P(X1, Z1);
Есть Figure, у котоорой кроме координат ничего нет, есть метод Draw, который переопр в каждой конкретной фигуре. Хотим написать прцедуру, которая по двум фигурам выдаёт пересечение. По какой фигуре объявлять её виртуальной? по первой или второй?
Последнее замечание:
насколько эффектевны/неэфф вирт методы.
Накладные расходы, которые связаны с введением ТВМ не оечень велики, но в программировании так говорить нельзя.
Пример: графический интерфейс пользователя.
У окон порядка полторы сотни событий, и реагируют только на единицы из них. В результате делается ТВМ на полторы сотни вирт методов, и так далее. Более того, большая часть элементов в одном экземпляре.
Решения Борланд не были приняты. В МФЦ используется куча дефанов и message map, в шарп – механизм делегатов.
Главав 3. Абстрактные классы и интерфейсы
АК != АТД
Рассмотрим иеархию фигур. Возникает вопрос, как определять рисование фигуры, ведь мы определять его должны, иначе ошибку выдадет загрузчик о том, что процедура не инициализирована.
Классы верхнего уровня в подобных иерархиях – заглушки. От рисования фигуры требуется только интерфейс.
Абстрактный класс нельзя создавать в большинстве языков (в дельфи можно).
В С++ есть термин чистая виртуальная функция (pure virtual)
Языки Программирования
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Календарь
чт | вт | чт | вт | чт | вт | чт | вт | чт | вт | |
Сентябрь
| 05 | 07 | 12 | 14 | 19 | 21 | 26 | 28 | ||
Октябрь
| 03 | 05 | 10 | 12 | 17 | 19 | 24 | 26 | 31 | |
Ноябрь
| 02 | 14 | 16 | 21 | 23 | 28 | 30 | |||
Декабрь
| 05 | 07 | 12 | 14 | 19 |