Апреля лекция пропущена!!!

 

24 апреля 2012г.

 

…//продолжение

Однако, через указатель на базовый класс можно обратиться по наследованным членам класса. О членах производного класса такой указатель ничего не знает.

Арифметика указателей связана с типом указателя. Поэтому, если указатель базового класса адресует объект производного класса и «инкрементируется», то это не приведёт к тому, что указатель будет ссылаться на следующий объект производного класса.

Указатель на производный класс нельзя использовать для адресации других объектов, в т.ч. объектов базового класса.

Виртуальные функции — функции, адрес вызова которых определяется только во время выполнения программы.

Если класс содержит хотя бы одну виртуальную функцию, то такой класс называется полиморфным. Для каждого полиморфного класса создается таблица виртуальных методов, которая называется virtual function table. Для каждого виртуального метода в эту таблицу записывается адрес памяти. Порядок записи адресов таблицы определяется описанием виртуальных методов в классе. Адрес виртуального метода имеет в таблице одно и то же смещение для каждого класса в пределах иерархии. Каждый объект полиморфного класса содержит дополнительное скрытое поле-ссылку на таблицу, называемое виртуальный указатель. Это поле заполняется конструктором при создании объекта. Для этого компилятор добавляет в начало тела конструктора соответствующие инструкции. На этапе компиляции ссылки на виртуальные методы заменяются на обращения к виртуальной таблице через виртуальный указатель объекта. На этапе выполнения в момент обращения к методу из таблицы выбирается адрес этого метода. Таким образом вызов виртуального метода в отличии от обычного метода включает дополнительный этап получения адреса метода из таблицы виртуальных методов. Это замедляет работу программы и кроме того хранения таблицы виртуальных методов требует определенных затрат памяти. Четкого правила, по которому метод нужно делать виртуальным не существует. Рекомендуется объявлять виртуальными методами для которых есть вероятность, что они будут переопределены в производных классах. Методы, которые во всей иерархии останутся неизменными, или те, которыми производные классы не будут пользоваться, делать виртуальными нет смысла. С другой стороны, при проектировании иерархии класса не всегда можно предсказать каким образом будут расширяться базовые классы, а объявление метода виртуальным обеспечивает гибкость и возможность расширения.

 

Виртуальные функции.

Чтобы функция базового класса стала виртуальной в ее объявлении необходимо использовать ключевое слово virtual. Это слово м.б. переведено как «фактически», указывая на то, что ссылка на такую функцию осуществляется по факту вызова. Если класс, содержащий виртуальную функцию, наследуется, то в производном классе виртуальная функция должна переопределяться. Таким образом, виртуальная функция реализует принцип «один интерфейс, множество методов».

Виртуальная функция в базовом классе определяет вид этой функции.

 

//--//--//текст пропущен//--//--//

Виртуальные деструкторы.

Конструкторы не могут быть виртуальными, а деструкторы можно объявлять виртуальными. Использование виртуального деструктора позволит избежать утечки памяти. Эта утечка памяти может произойти в результате следующего:

Указатель базового класса может использоваться для адресации объектов производного класса.

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

 

//--//--//текст пропущен//--//--//