Программирование на языке высокого уровня. Марапулец Ю.В. - 97 стр.

UptoLike

Составители: 

Виртуальный метод не может объявляться с модификатором static, но может быть
объявлен как дружественный.
Если в классе вводится описание виртуального метода, он должен быть определен
хотя бы как
чисто виртуальный.
Чисто виртуальный метод содержит признак - 0 вместо тела, например:
virtual void f(int)= 0;
Чисто виртуальный метод должен переопределяться в производном классе (воз-
можно, опять как чисто виртуальный).
Если определить метод func в классе A как виртуальный, решение о том, метод ка-
кого класса вызвать, будет приниматься в зависимости от типа объекта, на который ссы-
лается указатель:
A *r, *р;
r = new A; // Создается объект класса
A р = new B; // Создается объект класса B
r->func(1, 1); // Вызывается метод A:: func
p->func(1, 1); // Вызывается метод B::func
p->A::func(1, 1); //Обход механизма виртуальных методов
Итак,
виртуальным называется метод, ссылка на который разрешается на
этапе выполнения программы (ссылка разрешается по факту вызова).
Для каждого класса, содержащего хотя бы один виртуальный метод, компилятор
создает
таблицу виртуальных методов (vtbl), в которой для каждого виртуального ме-
тода записан его адрес в памяти. Адреса методов содержатся в таблице в порядке их
описания в классах. Адрес любого виртуального метода имеет в vtbl одно и то же сме-
щение для каждого класса в пределах иерархии.
Каждый объект содержит скрытое дополнительное
поле ссылки на vtbl, называе-
мое vptr. Оно заполняется конструктором при создании объекта (для этого компилятор
добавляет в начало тела конструктора соответствующие инструкции).
На этапе компиляции ссылки на виртуальные методы заменяются на обращения к
vtbl через vptr объекта, а на этапе выполнения в момент обращения к методу его адрес
выбирается из таблицы. Таким образом, вызов виртуального метода, в отличие от обыч-
ных методов и функций, выполняется через дополнительный этап получения адреса ме-
тода из таблицы. Это несколько замедляет выполнение программы.
Рекомендуется делать виртуальными деструкторы для того, чтобы гарантировать
правильное освобождение памяти из-под динамического объекта, поскольку в этом слу-
чае в любой момент времени будет выбран деструктор, соответствующий фактическому
типу объекта. Деструктор передает операции delete размер объекта, имеющий тип size_t.
Если удаляемый объект является производным и в нем не определен виртуальный дест-
руктор, передаваемый размер объекта может оказаться неправильным.
Деструктор класса, порожденного из класса с виртуальным деструктором, сам яв-
ляется виртуальным. Например:
class color
{
public:
virtual ~color(); // виртуальный деструктор
};
class red: public color
{
97
•  Виртуальный метод не может объявляться с модификатором static, но может быть
   объявлен как дружественный.
• Если в классе вводится описание виртуального метода, он должен быть определен
   хотя бы как чисто виртуальный.
Чисто виртуальный метод содержит признак - 0 вместо тела, например:

virtual void f(int)= 0;

     Чисто виртуальный метод должен переопределяться в производном классе (воз-
можно, опять как чисто виртуальный).
     Если определить метод func в классе A как виртуальный, решение о том, метод ка-
кого класса вызвать, будет приниматься в зависимости от типа объекта, на который ссы-
лается указатель:

A *r, *р;
r = new A;           // Создается объект класса
A р = new B;          // Создается объект класса B
r->func(1, 1); // Вызывается метод A:: func
p->func(1, 1); // Вызывается метод B::func
p->A::func(1, 1); //Обход механизма виртуальных методов

      Итак, виртуальным называется метод, ссылка на который разрешается на
этапе выполнения программы (ссылка разрешается по факту вызова).
      Для каждого класса, содержащего хотя бы один виртуальный метод, компилятор
создает таблицу виртуальных методов (vtbl), в которой для каждого виртуального ме-
тода записан его адрес в памяти. Адреса методов содержатся в таблице в порядке их
описания в классах. Адрес любого виртуального метода имеет в vtbl одно и то же сме-
щение для каждого класса в пределах иерархии.
      Каждый объект содержит скрытое дополнительное поле ссылки на vtbl, называе-
мое vptr. Оно заполняется конструктором при создании объекта (для этого компилятор
добавляет в начало тела конструктора соответствующие инструкции).
      На этапе компиляции ссылки на виртуальные методы заменяются на обращения к
vtbl через vptr объекта, а на этапе выполнения в момент обращения к методу его адрес
выбирается из таблицы. Таким образом, вызов виртуального метода, в отличие от обыч-
ных методов и функций, выполняется через дополнительный этап получения адреса ме-
тода из таблицы. Это несколько замедляет выполнение программы.
      Рекомендуется делать виртуальными деструкторы для того, чтобы гарантировать
правильное освобождение памяти из-под динамического объекта, поскольку в этом слу-
чае в любой момент времени будет выбран деструктор, соответствующий фактическому
типу объекта. Деструктор передает операции delete размер объекта, имеющий тип size_t.
Если удаляемый объект является производным и в нем не определен виртуальный дест-
руктор, передаваемый размер объекта может оказаться неправильным.
      Деструктор класса, порожденного из класса с виртуальным деструктором, сам яв-
ляется виртуальным. Например:

class color
{
      public:
        virtual ~color(); // виртуальный деструктор
};
class red: public color
{

                                             97