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;
//
чисто виртуальная функция
Бьерн Страуструп.
Язык программирования С++
157
};
Класс, в котором есть виртуальные функции, называется абстрактным. Объекты такого класса создать
нельзя:
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.
После введения абстрактного класса у нас есть все основные средства для того, чтобы написать
законченную программу.
Бьерн Страуструп.
Язык программирования С++
158
Достарыңызбен бөлісу: |