Опубликован: 10.10.2006 | Доступ: свободный | Студентов: 6440 / 527 | Оценка: 4.26 / 3.88 | Длительность: 31:30:00
Лекция 6:

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

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.

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

Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?