Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Козак Н.В. Лекции Основы создания программ в Си...doc
Скачиваний:
24
Добавлен:
23.09.2019
Размер:
2.24 Mб
Скачать

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

Функции класса могут объявляться в C++ как виртуальные. Ключевое слово virtual заставляет компилятор генерировать для класса некоторую дополнительную информацию о функции. Происходит следующее: если виртуальная функция переопределяется в производном классе, и если имеется указатель или ссылка на базовый класс (которые могут с тем же успехом ссылаться на производный класс, поскольку производный объект есть в то же время и объект базового класса), то при обращении к функции через указатель (ссылку) будет вызвана функция правильного класса (т.е. соответствующая типу действительного объекта), — базового или одного из производных классов, в зависимости от типа конкретного объекта.

#include <stdio>

class One { // Базовый класс.

public:

virtual void showVirt() // Виртуальная функция.

{

printf("It's One::showVirt()!\n");

}

void showNonVirt() // He-виртуальная функция.

{

printf ("It's One: :showNonVirt() !\n") ;

}

};

class Two: public One { // Производный класс.

public:

virtual void showVirt()

{

printf("It's Two::showVirt()!\n");

}

void showNonVirt()

{

printf("It's Two::showNonVirt()!\n");

}

};

int main(void)

{

Two derived;

One *pBase = &derived;

pBase->showVirt{); // Вызовет Two::showVirt().

pBase->showNonVirt(); // Вызовет One::showNonVirt().

//

// Следующий вызов подавляет виртуальный механизм:

//

pBase->One::showVirt(); // Явно вызывает One::showVirt().

return 0;

}

Результат работы программы (Рис. 8) показывает, что при обращении к виртуальной функции через базовый указатель будет вызвана «правильная» функция, соответствующая типу действительного (производного) объекта.

Рис. 8

Ключевое слово virtual при объявлении функции в производных классах не обязательно. Функция, однажды объявленная виртуальной, остается таковой во всех производных классах иерархии.

Виртуальная функция не может быть статической.

Чисто виртуальные функции и абстрактные классы

Виртуальная функция некоторого класса может быть объявлена чистой. Это выглядит так:

virtual тип имя_функции(список_параметров) = 0;

Другими словами, тело функции объявляется как =0 (т. н. чистый спецификатор). Действительная реализация ее не нужна (хотя и возможна). Предполагается, что чисто виртуальная функция будет переопределяться в классах, производных от него. Класс, объявляющий одну или несколько чисто виртуальных функций, является абстрактным базовым классом. Нельзя создать представитель такого класса. Он может служить только в качестве базового для порождения классов, которые полностью реализуют его чисто виртуальные функции.

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

Абстрактные классы

□ не могут, как уже сказано, иметь представителей;

а не могут использоваться в качестве типа параметров или возвращаемых значений;

□ не могут участвовать в явных приведениях типа.

Тем не менее, можно объявлять указатели или ссылки на абстрактный класс.

Смысл абстрактных базовых классов в том, что они способствуют лучшей концептуальной организации классовой иерархии и позволяют тем самым в полной мере использовать преимущества виртуальных механизмов C++.

Сказанное иллюстрирует следующий набросок иерархии классов:

class Shape { // Абстрактный базовый класс.

public:

virtual ~Shape() {} //На всякий случай...

virtual void draw() =0; // Чисто виртуальная функция. // . . .

//

// Производные классы:

//

class Line: public Shape {

// . . . public:

void draw()

{

// Определение тела draw...

}

// . . .

class Rectangle: public Shape {

//.... public:

void draw()

{

// ...

}

// . ..