    После, удаления этого объекта (строка 25) в строке 27 создается объект 
производного класса TMult. Coгласно: правилу использования указателей на классы в 
C++ указатель basep может ссылаться на объект производного  класса, даже если бы он 
был объявлен указателем на объект класса TValue. Поскольку basep ссылается на 
объект типа TMult, строка 28 отображает значение 20. 
    Внимательно сравните операторы вывода в строках 24 и 28. Как вы можете 
убедиться, исключая комментарии в конце строки, эти операторы абсолютно идентичны. 
Но как два одинаковых оператора могут дать разный результат? Ответ прост — 
объекты, на которые ссылается указатель, сами определяют для себя, какой из двух 
виртуальных функций-членов GetValueO следует вызвать. И что еще важнее, это 
решение принимается программой во время выполнения, а не компилятором или программистом. 

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

    Чистая виртуальная функция-член — пустое место, ожидающее своего 
заполнения производным классом. 
     Объявляется чистая виртуальная функция точно так же, как и обычная, только 
ее объявление в классе завершается  = 0. Например, в классе 
   class AbstractClass    {  
   public: 
      virtual void f1(void);         // Обычная виртуальная функция-член 
      virtual void f2(void) = 0;  // Чистая виртуальная функция-член 
    } 

   f2()  - чистая виртуальная функция-член. Компилятору не потребуется реализация 
функции-члена f2(), в отличие от остальных функций-членов, объявленных в классе. 
   Если класс содержит хотя бы одну виртуальную функцию-член, он называется 
абстрактным классом. Подобно любой абстрактной идее, абстрактный класс описывает 
нереализованные концепции. Абстрактный класс —  лишь схема, на основании которой 
вы собираетесь создавать производные классы. В C++ вы не можете создавать  
объекты,   имеющие  типы   абстрактных  классов.   Например,   вы  не  сможете  
объявить объект  типа AbstractClass. Если вы предпримете попытку скомпилировать 
следующую строку: 

    AbstractClass anyObject;	// ??? 

    Компилятор выдаст сообщение об ошибке "Cannot create an instance of class 
'AbstractClass' (He могу создать класса 'AbstractClass'). Конечно, другие функции-члены 
класса AbstractClass могут вызывать чистую виртуальную функцию-член. Например, 
функция-член f1() может вызвать f2(): 

   void AbstractClass: :f1(void) 
   {
      f2();	// Вызвать чистую виртуальную функцию-член 
      .....      //  Прочие операторы f1() 
    }

    Для того чтобы использовать абстрактный класс, следует вывести из него 
новый класс: 

    class MyClass:   public AbstractClass { 
    public:
      virtual void f2(void);	// Бывшая чистая виртуальная функция                
      .........
     }

     Производный класс MyClass наследует чистую виртуальную функцию-член,  но 
объявляет ее без = 0. ( Включение этого фрагмента сделает класс MyClass абстрактным.) 
Где-нибудь в другом месте следует реализовагь функцию-член f2(): 

    void MyClass::f2(void) 
    {

    _	// Операторы функции-члена 

    }

    Обращения к первоначальной чистой виртуальной функции-члену, как это 
реализовано, к примеру, в данном  случае с AnyClass::f1(), теперь переадресованы 
MyClass::f2(). С помощью простых объявлений чистых янпуалъных функций-членов 
в производном классе вы можете вставлять заглушки в код, которые могут быть другими 
функциями-членами, исключая в дальнейшем необходимость изменения и даже 
повторной компиляции этих членов. Чистые виртуальные функции подобны крючкам, на 
которые вы можете цеплять код  производных классов. 
    Теперь, когда все виртуальные функции-члены реализованы, компилятор сможет 
воспринять объекты типа <MnClass: 

    MyClass myObject; 

    Выполнение оператора	

    myObject.f1 ();	

    приведет к вызову наследованной f1(), которая вызовет f2() из MyClass.	: 


    14. Объектно-ориентированное программирование 355 
