#include <iostream>
using namespace std;
class figure {
protected:
double x, y;
public:
void set_dim(double i, double j=0) {
x = i;
у = j;
}
virtual void show_area() {
cout << "Для этого класса выражение вычисления ";
cout << "площади не определено.\n";
}
};
class triangle : public figure {
public:
void show_area() {
cout << "Треугольник с высотой ";
cout << x << " и основанием " << у;
cout << " имеет площадь ";
cout << х * 0.5 * у << ".\n";
}
};
class rectangle : public figure {
public:
void show_area() {
cout << "Прямоугольник с размерами ";
cout << x << " x " << у;
cout << " имеет площадь ";
cout << х * у << ".\n";
}
};
class circle : public figure {
public:
void show_area() {
cout << "Круг с радиусом ";
cout << x;
cout << " имеет площадь ";
cout << 3.14 * x * x << ".\n";
}
};
int main()
{
figure *p; // создаем указатель на базовый тип
triangle t; // создаем объекты производных типов
rectangle r;
circle с;
р = &t;
p->set_dim(10.0, 5.0);
p->show_area();
р = &r;
p->set_dim(10.0, 5.0);
p->show_area();
р = &с;
p->set_dim(9.0);
p->show_area();
return 0;
}
При выполнении эта программа генерирует такие результаты.
Треугольник с высотой 10 и основанием 5 имеет площадь 25.
Прямоугольник с размерами 10 х 5 имеет площадь 50.
Круг с радиусом 9 имеет площадь 254.34.
Как вы могли убедиться, если виртуальная функция, которая не переопределена в производном классе, вызывается объектом этого производного класса, то используется версия, определенная в базовом классе. Но во многих случаях вообще нет смысла давать определение виртуальной функции в базовом классе. Например, в базовом классе figure (из предыдущего примера) определение функции show_area() — это просто заглушка. Она не вычисляет и не отображает площадь ни одного из объектов. Как вы увидите при создании собственных библиотек классов, в том, что виртуальная функция не имеет значащего определения в контексте базового класса, нет ничего необычного.
Чисто виртуальная функция — это виртуальная функция, которая не имеет определения в базовом классе.
Существует два способа обработки таких ситуаций. Первый (он показан в предыдущем примере программы) заключается в обеспечении функцией вывода предупреждающего сообщения. Возможно, такой подход и будет полезен в определенных ситуациях, но в большинстве случаев он попросту неприемлем. Например, можно представить себе виртуальные функции, без определения которых в существовании производного класса вообще нет никакого смысла. Рассмотрим класс triangle. Он абсолютно бесполезен, если в нем не определить функцию show_area(). В этом случае имеет смысл создать метод, который бы гарантировал, что производный класс действительно содержит все необходимые функции. В C++ для решения этой проблемы и предусмотрены чисто виртуальные функции.