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



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.
      После введения абстрактного класса у нас есть все основные
 средства для того, чтобы написать законченную программу.

 
« Предыдущая статья   Следующая статья »