Опубликован: 10.10.2006 | Доступ: свободный | Студентов: 5981 / 453 | Оценка: 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.

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

Дарья Федотова
Дарья Федотова
Сергей Березовский
Сергей Березовский

В рамках проф. переподготовки по программе "Программирование"

Есть курсы, которые я уже прошел. Но войдя в курс я вижу, что они не зачтены (Язык Ассемблера и архитектура ЭВМ, Программирование на С++ для профессионалов). Это как?

Сергей Мороз
Сергей Мороз
Беларусь
Валентина Зубарева
Валентина Зубарева
Россия, Рязань, РГРТУ, 2011