- •Часть 1. Основы создания программ в Си Лекция.1.Язык Си
- •Технология разработки программ
- •Базовые элементы языка Си
- •Представление данных в Си
- •Встроенные типы данных
- •Переменные
- •Операции и выражения
- •Функции
- •Лекция.2.Язык Си Обзор элементов языка Си Типизированные константы
- •Область действия переменных
- •Управляющие конструкции с
- •Массивы и указатели
- •Типы, определяемые пользователем
- •Лекция.3.Препроцессор и отладка программ
- •Макроопределения
- •Условная компиляция
- •1. Предотвращение включения файлов
- •Отладка программ
- •Элементы отладки
- •Лекция.1.Объектно-ориентированное программирование
- •Что такое объектно-ориентированное программирование
- •Пример определений классов
- •Конструктор и деструктор
- •Элементы класса
- •Элементы-функции
- •Элементы данных
- •Класс как область действия
- •Указатель this
- •Лекция.3.Элементы класса Статические элементы класса
- •Статические элементы-функции
- •Специальные элементы-функции класса
- •Конструктор
- •Список инициализации элементов
- •Конструктор копии
- •Операция присваивания
- •Деструктор
- •Операции класса new и delete
- •Функции преобразования
- •Ключевое слово explicit
- •Операции приведения
- •Доступ к базовым классам
- •Простое наследование
- •Конструкторы, деструкторы и наследование
- •Сложное наследование
- •Неоднозначности при сложном наследовании
- •Виртуальные базовые классы
- •Виртуальные функции
- •Чисто виртуальные функции и абстрактные классы
- •Реализация виртуального механизма
- •Лекция.5.Семинар 1-2: Обработка исключений
- •Объекты-исключения
- •Повторное возбуждение исключения
- •Перехват всех исключений
Виртуальные функции
Функции класса могут объявляться в 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()
{
// ...
}
// . ..