C++ Программирование в среде С++ Builder 5

Чисто виртуальные функции и абстрактные классы


Виртуальная функция-элемент некоторого класса может быть объявлена чистой. Это выглядит так:

virtual тип имя функции(список параметров} = 0;

Другими словами, тело функции объявляется как ='0 (т. н. чистый спецификатор). Действительная реализация ее не нужна (хотя и возможна). Предполагается, что чисто виртуальная функция будет переопределяться в классах, производных от него. Класс, объявляющий одну или несколько чисто виртуальных функций, является абстрактным базовым классом. Нельзя создать представитель такого класса. Он может служить только в качестве базового для порождения классов, которые полностью реализуют его чисто виртуальные функции.

Если класс не определяет see чисто виртуальные функции абстрактного базового класса, то он также является абстрактным.

Абстрактные классы

  • не могут, как уже сказано, иметь представителей;
  • не могут использоваться в качестве типа параметров или возвращаемых значений;
  • не могут участвовать в явных приведениях типа.
  • Тем не менее, можно объявлять указатели или ссылки на абстрактный класс.

    Смысл абстрактных базовых классов в том, что они способствуют лучшей концептуальной организации классовой иерархии и позволяют тем самым в полной мере использовать преимущества виртуальных механизмов C++.

    Предположим опять-таки, что вы хотите работать с геометрическими фигурами — линиями, кругами и т. д. Конечно, имеет смысл определить общий базовый класс “фигура”. Тогда можно будет представлять наборы разнородных фигур в виде единообразных списков или массивов указателей. Но нет смысла создавать представителей собственно класса “фигура”. Не бывает в мире фигур просто. Фигура — это абстракция.



    С другой стороны, каждый конкретный класс фигур должен иметь метод “нарисовать”. Чтобы этот метод был виртуальным, его должен объявлять базовый класс (как виртуальный, естественно). Но что может делать такой метод, если неизвестно, что рисовать? Конечно, можно написать функцию, которая ничего не делает или возвращает состояние ошибки. Но гораздо лучше объявить такую функцию-элемент базового класса как чистую. Тем самым будет образована виртуальная база для переопределения в производных классах, а также запрещено явное или неявное создание представителей базового класса.

    Сказанное иллюстрирует следующий набросок иерархии классов:

    class Shape { // Абстрактный базовый класс.

    // . . .

    public:

    virtual -Shape () {} //На всякий случай...

    virtual void Draw() =-0; //Чисто виртуальная функция. // . . . };

    //

    // Производные классы:

    //

    class Line: public Shape

    { // . . . public:

    void Draw() {

    // Определение тела

    class Rectangle: public Shape

    {

    // . . .

    public:

    void Draw()

    {

    // . . .

    }

    //...

    // И т.д.



    Содержание раздела