- •Курсовая работа
- •Часть I. Разработка гипотетической машины.
- •1.Цель работы Целью данной курсовой работы является изучение стандартных макросредств ассемблера ibm pc.
- •2.Задание
- •3.Введение
- •4.Постановка задачи
- •5.Разработка алгоритма
- •Задачи удаления лишних знаков препинания и определения длины каждого слова не являются сложными и их можно реализовать не разбивая их на подзадачи.
- •BeginProg – Инициализация программы. Здесь производится привязка сегментных регистров к соответствующим сегментам.
- •6.Алгоритм
- •7.Результаты
- •8.Листинг программы
- •Часть II. Самостоятельная работа
- •Основные понятия и определения.
- •Описание типов и экземпляров объектов
- •Скрытые поля и методы.
- •Как сказано выше приватные поля и методы должны располагатся после общедоступных. Директива public позволяет, если это удобно, расположить их наоборот.
- •Наследование и переопределение .
- •Статические и виртуальные методы.
- •Виртуальные методы и полиморфизм.
- •Совместимость объектных типов.
- •Преимущества и недостатки виртуальных методов.
- •Заключение
- •Литература
Статические и виртуальные методы.
Пусть заданы следующие объекты:
объект – сотрудники:
Type
TStaff = object
Name : String[30];
Money : Real;
Function GetSum : Real;
end;
объект – студент:
Type
TStudent = object (TStaff)
Ball : Real;{средний балл}
end;
Рассмотрим процедуру ShowSum которая выводит размер выплаты денежных средств:
для типа TStudent она имеет вид:
procedure TStudent.ShowSum;
begin
writeln(GetSum);
end;
где GetSum – некая функция возвращающая размер денежных выплат.
Для типа TStaff имеем:
procedure TStaff.ShowSum;
begin
writeln(GetSum);
end;
Видно, что обе процедуры схожи. Возникает вопрос: нет ли здесь логической ошибки?
Поскольку методы одинаковы , нет нужды помещать ShowSum в TStudent и TStaff. Т.к. TStudent автоматически наследуtт ShowSum от TStaff , поэтому нет необходимости переопределять этот метод. Но именно здесь и возникает ошибка, связанная со статическим методом.
Проблема заключается в следующем:
пока копия метода ShowSum не будет помещена в область действия TStudent для подавления метода ShowSum объекта TStaff , метод не бкдет работать правильно , если он будет вызываться из объекта типа TStudent . Если TStudent запускает метод ShowSum объекта TStaff , то и функция GetSum , используемая в методе, будет принадлежать объекту TStaff и стипендия будет расчитана неправильно, без учета среднего балла.
Это объясняется способом , которым компилятор осуществляет вызов методов.
Поскольку тим TStudent является потомком типа TStaff то сначала в сегмент кода будет скомпилирована функция TStaff.GetSum. Затем процедура TStaff.ShowSum вызывающая
TStaff.GetSum. Как и при вызове любой процедуры, компилятор замещает ссылки на TStaff.GetSum и TStaff.ShowSum в исходном коде на их адреса в сегменте кода. Т.о. при вызове код TStaff.ShowSum в свою очередь вызывает TStaff.GetSum, что исосавляет проблему. Фактически , наследуется следующая процедура:
procedure TStaff.ShowSum;
begin
writeln(TStaff.GetSum);
end;
Попросту говоря , метод объекта TStaff ничего не знает о существовании объекта TStudent . Т.о. метод ShowSum нельзя наследовать. Вместо этого он должен быть переопределен своей второй копией , вызывающей уже правильный метод.
Вызывая методы компилятор работает так:
сначала он ищет метод , имя которого внутри типа объекта. Тип TStudent определяет методы с именами GetSum, ShowSum. Если бы объект типа TStudent должен был вызывать один из этих методов, компилятор заменил бы его вызов на адрес одного из собственных методов TStudent.
Если в типе объекта не определен метод с таким именем, то компилятор поднимается выше к непосредственному родительскому типу в поисках метода с указанными именами. Если метод с таким именем найден, адрес родительского метода в исходном коде замещается адресом дочернего метода. Если не найден , то компилятор продолжает двигаться вверх по родительским объектам в поисках метода.
Если статический метод найден , то необходимо помнить , что вызываемый метод является в точности таким же как он был определен и скомпилирован для родительского типа.
Т.о. с помощью статических методов реализовать полиморфические действия не возможно, т.к. привязка адресов методов (процедур, функций) к экземплярам объектов выполняется статически. Поэтому для реализации полиморфизма требуются не статическое, а динамическое связывание экземпляров объектов с методами, которые поддерживают полиморфические действия.
