Определим класс shape с двумя виртуальными функциями элементами:
class shape {
public:
double xo, yo;
shape(double x, double y); // Конструктор создания shape (фигуры)
virtual double area(void); // Функция вычисляющая поверхность
virtual void draw(void); // Функция рисования shape
};
Ниже показано, как устроен просмотр таблицы виртуальных функций
объектами данного класса.
Данные объекта Таблица Нужная
shape виртуальных функция
функций
>
xo, yo (*area)() * > shape::area()
vptr * (*draw)() * > shape::draw()
При вызове объектов shape функцией draw(), выполняется подстановка кода следующим образом:
My_shape.draw() > *my_shape.vptr1([]);
Каждая виртуальная функция элемент проиндексирована в таблице.
Это индексирование выполняется во время компиляции.
Для создания новых классов из shape можно использовать наследование и порождение.
class circle : public shape {
public:
double radius;
circle(double x, double y, double r);
double area(void); // Переопределяет shape::area()
void draw(void); // Переопределяет shape::draw()
};
Ниже показано, как устроен будет устроен просмотр таблицы виртуальных функций элементов сейчас:
Данные объекта Таблица Нужная
circle виртуальных функция
функций
>
xo, yo (*area)() * > circle::area()
radius
(*draw)() * > circle::draw();
vptr *
Класс circle копируют таблицу виртуальных функций элементов из
класса shape. Каждая виртуальная функция переопределяется классом
circle путем передачи входов модифицированной таблице.
Таблицы виртуальных функций элементов позволяют однозначно
использовать указатели на объекты и гарантировать точность вызова
виртуальных функций.
shape *p; // Объявление родового указателя shape
shape s(0,0); // исходной точки фигуры shape
circle c(10,10,50); // и круга circle фигуры shape
p = &s; // Точка фигуры shape
p->draw(); // Вызов shape::draw()
p = &c; // Точка круга circle
p->draw(); // Вызов circle::draw()
Так c помощью виртуальных функций мы можем управлять поведением
объектов. Вот таков полиморфизм в действии.
Обсудим порядок объявления виртуальных функций элементов.