Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛЕКЦИИ Программирование и основы алгоритмизации...doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.5 Mб
Скачать

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

1) Если в базовом классе функция-элемент определена как виртуальная, то функция-элемент, определенная в производном классе с тем же именем и тем же набором параметров, автоматически становится виртуальной, а с отличающимся набором параметров – обычной.

2) Виртуальные функции наследуются, поэтому переопределять их нужно только при отличиях. Права доступа при переопределении изменить нельзя.

3) Если виртуальная функция-элемент переопределена в производном классе, объекты этого класса могут получить доступ к функции-элементу базового класса с помощью операции (::).

4) Виртуальные функции не могут быть static, но могу быть friend.

5) В базовом классе виртуальная функция может быть определена как чистая виртуальная:

virtual ……()=0;

6) Чистая виртуальная функция должна переопределяться в производном классе (возможно, опять как чистая виртуальная).

Если в классе point функцию-элемент определить как виртуальную

virtual float getx() const;

решение о том, функция-элемент какого класса будет вызвана, будет приниматься в зависимости от типа объекта, на который ссылается указатель.

point *p, *c;

p=new point; //создается объект класса point

c=new circle; // создается объект класса circle

p->getx(); //вызывается функция—элемент point::get()

c->getx(); // вызывается функция—элемент circle::get()

Для обхода механизма виртуальных функций нужно:

c->point::getx();

Примечания.

1) Виртуальной называется функция, ссылка на которую разрешается на этапе выполнения программы.

2) Виртуальный механизм работает только при использовании указателей или ссылок на объекты.

3) Деструкторы рекомендуется делать виртуальными для того, чтобы правильно освобождать память из-под динамического объекта (операцией delete), поскольку в этом случае в любой момент времени будет выбран деструктор, соответствующий фактическому типу объекта.

Позднее (динамическое) связывание

Для каждого класса, содержащего хотя бы одну виртуальную функцию-элемент, компилятор создает таблицу виртуальных функций (vtbl), в которой для каждой виртуальной функции записан её адрес в памяти. Адреса виртуальных функций содержатся в таблице в порядке их описания в классах. Адрес любой виртуальной функции имеет в vtbl одно и то же смещение для каждого класса в пределах иерархии.

Каждый объект содержит скрытое дополнительное поле ссылки на vtbl, называемое vptr. Поле vptr заполняется конструктром при создании объекта. Для этого компилятор добавляет в начало тела конструктора соответствующие инструкции.

На этапе компиляции ссылки на виртуальные функции заменяются на обращение к vtbl через vptr объекта, а на этапе выполнения в момент обращения к виртуальной функции её адрес выбирается из таблицы.

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

Полиморфизм. Абстрактные и конкретные классы

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

Абстрактным является класс, который не может порождать объекты. Он содержит хотя бы одну чистую виртуальную функцию. Можно объявлять указатели и ссылки на абстрактный класс, если при инициализации не требуется создавать временный объект. Конкретный класс может порождать объекты; в нем определены все функции-элементы.

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