Реально в конкретных задачах вызываются лишь функции производных классов. “Исходная” виртуальная функция базового класса часто нужна только для того, чтобы в производных классах было, что замещать.
Содержимое базовой функции в этом случае не имеет значения и может быть пустым.
class A {
public :
virtual void Func () { }
};
Это удобно если функция ничего не возвращает. Необходимо, чтобы все замещающие функции, а также базовая функция, имели и имя, и сигнатуру, и тип возвращаемого результата одинаковыми.
Если функции должны, что-либо возвращать, то базовая функция уже не может быть пустой. Она может возвращать произвольное значение, напр., 0:
virtual int Func () { return 0 ;}
Однако можно объявить в базовом классе чистую виртуальную функцию, для чего достаточно приравнять прототип этой функции нулю:
virtual int Func ( int, char*) =0;
Это абстракция и такую функцию обязательно надо замещать в производных класса, в которых она и наполнится разумным содержанием.
Объявление такой функции в базовом классе носит формальный характер для указания на виртуальность функций с данным именем.
Класс, в котором есть хоть одна чистая виртуальная функция, называется абстрактным классом.
Свойства абстрактного класса:
- Невозможно создать самостоятельных объектов абстрактного класса.
- Абстрактный класс может использоваться только в качестве базового класса для производных классов.
- Если в производном классе от абстрактного базового класса происходит замещение чистой виртуальной функции, то производный класс не является абстрактным.
Если замещение не производится, то производный класс также является абстрактным.
Class A { //абстрактный класс
public:
virtual int Func ( char*) =0;
void F ( );
};
class B: public A { // В - не абстрактный класс
. . .
int Func ( char*);
} ;
class C: public A {// С – также абстрактный класс
void F ( );
};
- Абстрактные классы предназначены для представления общих понятий, которые предстоит конкретизировать. На базе общих понятий строятся частные производные классы для описания конкретных объектов.
- Абстрактный класс может иметь явно определенный конструктор.
- Если все -таки предстоит создавать самостоятельные объекты базового класса, то исходные виртуальные функции следует определять не как чистую, а как пустую.
Рассмотрим программу, в которой на основе базового класса pointпостроен абстрактный класс figure.
В классеfigureопределены конструктор и чистая виртуальная функция для вывода изображения фигуры на экран show().
Однако реальное выполнение show()возможно только после создания производного класса, в котором чистая виртуальная функция будет заменена компонентной функцией show()для конкретной фигуры.
Кроме того, классfigureвключает еще функцииhide()– для удаления изображениефигуры иmove()– для передвижения фигуры. Обе функции вызывают в своем теле чистую виртуальную функциюshow().
// figure.cpp
#include “point.cpp”
class figure : public point {
public:
figure (point p) : point ( p. GetX(), p. GetY () ) { } // конструктор
virtual void show () =0; //функция для определения в производных классах