Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Вопрос-ответ 2013.doc
Скачиваний:
13
Добавлен:
22.02.2020
Размер:
182.78 Кб
Скачать

Виртуальные методы

К механизму виртуальных функций обращаются в тех случаях, когда в класс необходимо поместить функцию, которая выполняется в наследуемых классах иначе, чем в классе базовом. Виртуальные функции необходимы потому, что используются для поддержки динамического полиморфизма. Это свойство ООП поддерживается двумя способами: — на этапе компиляции, посредством перегрузки функций, и — во время выполнения программы, посредством виртуальных функций.  Виртуальные функции реализуют тезис: “один  интерфейс — множество методов“. Классы, содержащие одну или несколько виртуальных функций, называются полиморфными.

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

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

Метод делается виртуальным, когда за его определением в типе объекта ставится служебное (зарезервированное) слово Virtual. Надо запомнить, что если вы определяете метод в родительском типе как Virtual, все методы с тем же именем в любом из потомков также должны быть описаны как Virtual.

Раннее и позднее связывание

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

В терминах объектно-ориентированного программирования раннее связывание означает, что объект и вызов функции связываются между собой на этапе компиляции. Это означает, что вся необходимая информация для того, чтобы определить, какая именно функция будет вызвана, известна на этапе компиляции программы. В качестве примеров раннего связывания можно ука­зать стандартные вызовы функций, вызовы перегруженных функций и перегруженных операто­ров. Принципиальным достоинством раннего связывания является его эффективность — оно бо­лее быстрое и обычно требует меньше памяти, чем позднее связывание. Его недостатком служит невысокая гибкость.

Позднее связывание означает, что объект связывается с вызовом функции только вовремя ис­полнения программы, а не раньше. Позднее связывание достигается в С++ с помощью использо­вания виртуальных функций и производных классов. Его достоинством является высокая гиб­кость. Оно может использоваться для поддержки общего интерфейса, позволяя при этом различным объектам иметь свою собственную реализацию этого интерфейса. Более того, оно помогает со­здавать библиотеки классов, допускающие повторное использование и расширение.

Какое именно связывание должна использовать программа, зависит от предназначения про­граммы. Фактически достаточно сложные программы используют оба вида связывания. Позднее связывание является одним из самых мощных добавлений языка С++ к возможностям языка С. Платой за такое увеличение мощи программы служит некоторое уменьшение ее скорости испол­нения. Поэтому использование позднего связывания оправдано только тогда, когда оно улучша­ет структурированность и управляемость программы. Надо иметь в виду, что проигрыш в произ­водительности невелик, поэтому, когда ситуация требует позднего связывания, можно использовать его без всякого сомнения.

  1. Расширяемость объектов. Преимущества и недостатки виртуальных методов.

Новое понятие о добавлении функциональных характеристик в

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

ностью к расширению. Способность к расширению является естествен-

ным следствием наследования: вы наследуете все, чем обладают по-

рождающие типы, а затем добавляете новые нужные вам возможности.

Позднее связывание позволяет, чтобы новое связывалось со старым

во время выполнения программы, благодаря чему расширение сущест-

вующего кода выглядит "бесшовным" и стоит вам в части выполнения

не более, чем быстрое путешествие по таблице виртуального метода.

Разница между виртуальными и динамическими методами заключается в особенности поиска адреса. Когда компилятор встречает обращение к виртуальному методу объекта, он подставляет вместо прямого вызова по конкретному адресу код, который обращается к VMT этого объекта и извлекает оттуда нужный адрес. Такая таблица одна для каждого класса (объектного типа). В ней хранятся адреса всех виртуальных методов класса, независимо от того, унаследованы ли они от предка или перекрыты в данном классе. Отсюда и достоинства, и недостатки виртуальных методов: они вызываются сравнительно быстро, однако для хранения указателей на них в таблице VMT требуется большое количество памяти.

Динамические методы вызываются медленнее, но позволяют более экономно расходовать память. Каждому динамическому методу системой присваивается уникальный индекс. В таблице динамических методов класса хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе. При вызове динамического метода происходит поиск в этой таблице; в случае неудачи просматриваются таблицы DMT всех классов-предков в порядке иерархии и, наконец, TObject, где имеется стандартный обработчик вызова динамических методов. Экономия памяти налицо. Те, для кого это не очевидно или недостаточно, найдут подробности в разделе данной главы "Как устроен объект изнутри ".

  1. Абстрактные классы и методы. Конструкторы.

  2. Динамические объекты. Деструкторы.

  3. TBM, функции работы с TBM.

  4. Объектная декомпозиция. Пример.

  5. Диаграмма объектов предметной области, и диаграмма состояний интерфейса программы.

  6. Ассоциация и обобщение

  7. Простой и сложный полиморфизм

  8. Композиция и наполнение

  9. Контейнерные классы