    Следующие несколько листингов демонстрируют практический пример 
использования чистых виртуальны функций и абстрактных классов. Класс TSet 
может сохранять простое множество объектов произвольного типа. В листинге 
14.5 содержится объявление класса, а также другие вспомогательные объявления. 
Это всего лишь заголовочный файл, вы не сможете его скомпилировать. 

    Листинг 14.5.  SET.H (объявление класса TSet) 

    1:	// set.h -- Объявление класса TSet 
    2: 
    3:	#ifndef __SET_H 
    4:	#define _SET_H 1  // Предотвращение нескольких «include 
    5: 
    6:	class TElem; 
    7:	typedef TElem *PTElem; 
    8:	typedef PTElem *PPTElem; 
    9: 
    10:	class TSet; 
    11:	typedef TSet *PTSet;   
    13:	class TSet {      
    14:	private:     
    15:	int max;    // Максимальное число элементов 
    16:	int index;   // Индекс массива множества 
    17:	PPTElem set; // Указатель на массив указателей на PTElem 
    18:	protected:                                    " 
    19:	  virtual int CompareElems(PTElem pi, PTElem p2) = 0; 
    20:	public: 
    21:	  TSet( int n ) 
    22:	      { max = n;  index = 0;  set = new PTElem[n];   } 
    23:	   virtual ~TSet() 
    24:	     { delete[] set;   } 
    25:	   void AddElem(PTElem p); 
    26:	   int HasElem(PTElem p);
    27:	}; 
    28: 
    29.    #endif       /I   __SET _H 
    
    Для того чтобы сделать класс TSet как можно более гибким, классу 
необходимо обеспечить его возможностью запоминать объекты классов незаданных 
типов. Как показано в строке 6, C++ позволяет делать неполные объявления 
классов, не имеющих тела: 

    class TElem;   // Неполное объявление класса	

    В соответствии с этим объявлением объекты класса TElem могут задаваться в 
параметрах функций, возвращаться функциями и т.д. Конечно, позже в программе 
должно присутствовать полное объявление класс TElem. Неполное описание класса 
дает возможность написания класса TSet без каких-либо привязок к конкретному 
типу объектов, которые будут запоминаться в классе. В строках объявляются два 
дополнительны символа, облегчающих чтение листинга. PTElem объявлен алиасом 
для TElem*. Другими словами, PTElem - указатель на объект типа TElem. 
Аналогично, PPTElem объявлен алиасом для указателя PTElem, т.е. указателем на 
указатель на объект типа TElem. В классе TSet алиас PPTElem используется для 
создания динамически изменяющего свой размер массива указателей PTElem. 
    В строках 10—11 похожие объявления используются для задания неполного 
описания класса TSet и алиас PTSet в качестве указателя на объект TSet. 
Единственная причина неполного объявления TSet в строке 10 - возможность 
компиляции последующего typedef-объявления. 
    Затем следует объявление класса TSet (строки 13-27). Три закрытых 
данных-члена скрывают детали внутренней реализации класса. В этой версии TSet 
множество хранится в массиве указателей PTElem, динамичесм изменяющем свой 
размер, указатель PPTelem используется для хранения адреса массива. (Член set 
— указател на массив указателей на объекты типа TElem.) Члены max и index 
используются для управления массивом. 

    СОВЕТ

    Поскольку все данные-члены класса TSet закрыты в классе, их можно изменить 
позже, не затрагивал операторы, использующие объекты класса. При написании 
классов часто бывает полезно выбирать простые если не идеально эффективные, 
методы сохранения данных класса. Как только вы сделаете эти данньв закрытыми в 
классе, вы всегда сможете изменить их позже, не затрагивая код, не 
принадлежащий классу, 

    В строке 19 объявляется чистая виртуальная функция-член CompareElems как 
защищенный член класо TSet. Чистые виртуальные функции-члены также могут быть 
и открытыми, но чаще всего они защищены, по 


    356 Часть III. Программирование на ANSI С++
