Бьерн Страуструп - Язык программирования С++. Главы 5-7

ОГЛАВЛЕНИЕ

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

Многие классы сходны с классом employee тем, что в них можно дать разумное определение виртуальным функциям. Однако, есть и другие классы. Некоторые, например, класс shape, представляют абстрактное понятие (фигура), для которого нельзя создать объекты. Класс shape приобретает смысл только как базовый класс в некотором производном классе. Причиной является то, что невозможно дать осмысленное определение виртуальных функций класса shape:
            class shape {
               // ...
            public:
               virtual void rotate(int) { error("shape::rotate"); }
               virtual void draw()  { error("shape::draw"): }
               // нельзя ни вращать, ни рисовать абстрактную фигуру
               // ...
            };
Создание объекта типа shape (абстрактной фигуры) законная, хотя совершенно бессмысленная операция:
           shape s;  // бессмыслица: ``фигура вообще''
Она бессмысленна потому, что любая операция с объектом s приведет к ошибке.

Лучше виртуальные функции класса shape описать как чисто виртуальные. Сделать виртуальную функцию чисто виртуальной можно, добавив инициализатор = 0:

           class shape {
             // ...
           public:
             virtual void rotate(int) = 0; // чисто виртуальная функция
             virtual void draw() = 0;      // чисто виртуальная функция
           };
Класс, в котором есть виртуальные функции, называется абстрактным. Объекты такого класса создать нельзя:
           shape s;   // ошибка: переменная абстрактного класса shape
Абстрактный класс можно использовать только в качестве базового для другого класса:
           class circle : public shape {
             int radius;
           public:
             void rotate(int) { } // нормально:
                                  // переопределение shape::rotate
             void draw();         // нормально:
                                  // переопределение shape::draw

             circle(point p, int r);
           };
Если чисто виртуальная функция не определяется в производном классе, то она и остается таковой, а значит производный класс тоже является абстрактным. При таком подходе можно реализовывать классы поэтапно:
           class X {
           public:
             virtual void f() = 0;
             virtual void g() = 0;
           };

           X b;   // ошибка: описание объекта абстрактного класса X

           class Y : public X {
             void f();  // переопределение X::f
           };

           Y b;   // ошибка: описание объекта абстрактного класса Y

           class Z : public Y {
             void g();  // переопределение X::g
           };

           Z c;   // нормально
Абстрактные классы нужны для задания интерфейса без уточнения каких-либо конкретных деталей реализации. Например, в операционной системе детали реализации драйвера устройства можно скрыть таким абстрактным классом:
           class character_device {
           public:
              virtual int open() = 0;
              virtual int close(const char*) = 0;
              virtual int read(const char*, int) =0;
              virtual int write(const char*, int) = 0;
              virtual int ioctl(int ...) = 0;
              // ...
           };
Настоящие драйверы будут определяться как производные от класса character_device.

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

Читайте также:
  • Встраивание Python в C/C++: первая часть
    • Скачать исходные файлы - 5.23Кб• Скачать демонстрационный проект - 80.6 Кб Введение Статья "Встраивание Python в многопоточные приложения C/C++" (Linux Journal) вдохновила на более глубокое освещение темы встраивания Python. Эта статья написана с двумя целями:1. Она написана для программистов,...
  • Как экспортировать классы C++ из DLL
    •    Скачать исходники - 11.1 Кб Введение Динамически подключаемые библиотеки (DLL) являются составной частью платформы Windows с самого ее начала. DLL позволяют инкапсулировать часть функционала в автономном модуле с точным списком функций C, доступных внешним пользователям. В 1980-е годы, когд...
  • Декомпиляция и вызов функции по адресу
    •    Скачать демо - 75.92 Кб•    Скачать исходный код - 8.36 Кб Необходимые инструменты Эта статья использует отладчик (OllyDbg можно бесплатно скачать тут) и инжектор DLL Winject (бесплатно скачивается через интернет и включен в callbin.zip). Нужен компилятор C++ для компиляции кода для DLL. Ко...
  • Типобезопасные обратные вызовы в C++
    •    Скачать исходники - 32.39 Кб•    Скачать документацию - 33.08 Кб Обсуждаемый класс добавляет типобезопасные обратные вызовы C++ в проекты. Его свойства заключаются в следующем:•    Любую функцию в любом классе можно вызвать откуда угодно в любом другом классе.•    Можно передать от 0 до 5 ар...
  • Написание приложений Win32 с помощью одних классов C++ (часть 4)
    • Скачать проект и демо - 97.7 Кб Добавленные возможности Макросы NOTIFY_xxx_HANDLER Есть макросы карты сообщений типа ATL, применяемые для отправки сообщений WM_NOTIFY. Благодаря их улучшению они принимают дополнительный параметр "type". Новая форма - GE_NOTIFY_xxx_TYPEDHANDLER( ... , func, t...