main.gif (47332 bytes)

InterReklama
InterReklama Advertising

РЕКЛАМА

5. Шаблоны функций и классов.

RLE Banner Network

TBN 100x100
TBN.ru
5.1. Шаблоны функций

Часто встречаются функции, реализующие одни и те же действия для аргументов различных типов. Например, сортировка массива по возрастанию его элементов может выполняться одним и тем же методом и для данных типа int и для данных типа double. Различие состоит только в типах параметров и некоторых внутренних переменных.

В более поздние версии С++ включено специальное средство, позволяющее параметризовать определение функции, чтобы компилятор мог построить конкретную реализацию функции для указанного типа параметров функции. Параметризованное определение функции строится по схеме:

template < class имя_класса >
          Заголовок функции
      { /* Тело функции */ }

Имя класса является параметром и задается идентификатором, локализованным в пределах определения функции. Хотя бы один из параметров функции должен иметь тип, соответствующий этому идентификатору.

Параметризованное определение функции сортировки массива методом перестановок может быть построено следующим образом:

template <class T >
  void sort ( T a[ ], int  n )
   {   T  temp;
      int sign;
      for ( int k = 0; k > n; k++)
       { sign = 0;
         for ( i = 0; i <n - k; i++)
          if ( a [ i ] > a [ i + 1])
             { temp = a [ i ];
               a[ i ] = a[ i + 1 ];
               a[ i + 1 ] = temp; sign++;
              }
          if ( sign == 0 ) break;
        }
       return;
  }

Если в программе будут объявлены массивы

int aint [10];
double afl [20];

и установлены значения элементов этих массивов, то вызов функции

  sort ( aint, 10 );

обеспечит вызов sort для упорядочения массива целых, а вызов функции

  sort ( afl , 20 )

обеспечит вызов sort для упорядочения массива с элементами типа double.

Если элементами массива являются объекты какого-либо определенного программистом класса, для которого определена операция отношения >, то функция sort может быть вызвана и для такого массива. Разумеется, в объектном коде программы будут присутствовать все варианты реально вызывамой функции sort. Параметризация функции сокращает объем исходного текста программы и повышает его надежность.

В описателе template можно указывать несколько параметров вида class имя_типа, а также параметры базовых типов. Например, функция

template < class T1, class T2 >
void copy ( T1 a[ ], T2 b[ ], int n)
      {  for ( int i = 0; i <n; i++)
          a[ i ] = b [ i ] ;
      }

копирует первые n элементов массива b типа T2 в первые n элементов массива a типа T1. Разумеется, программист несет ответственность за то, чтобы такое копирование было возможным.

5.2. Шаблоны классов

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

  template <class T >
        class  описание класса

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

В качестве примера приведем описание класса stack, предназначенного для построения стеков фиксированного максимального размера с элементами произволного типа.

enum BOOLEAN ( FALSE, TRUE );
template <class Type >
class stack
  { private:
    enum ( EMPTY = -1 );
    Type*     s;     /* Указатель на массив стека  */
     int      max_len;   /* Максимальная длина стека */
     int      top;     /* Индекс элемента в вершине стека */
    public:
     stack ( ) : max_len ( 100 ) /* конструктор без параметров */
      { s = new Type [ 100 ]; top = EMPTY; }
     stack ( int size ) : max_len( size ) /* Второй конструктор  */
      { s = new Type [ size ]; top = EMPTY; }
     ~stack ( ) { delete [ ] s;  }    /* Деструктор   */
     void reset ( )  { top = EMPTY; }   /* Очистить стек  */
     void push ( Type  c ) { s [ ++top ] = c; }
     Type pop ( ) { return  (s [top—] }
     Type top_of ( ) { return ( s [top ] }
     BOOLEAN  empty ( ) { return BOOLEAN ( top == EMPTY ) }
     BOOLEAN  full  ( ) { return BOOLEAN ( top == max_len ) }
   };

Следует отметить, что в этом примере с целью сокращения исходного текста не предусмотрен контроль выхода за пределы стека в методах push и pop.

Чтобы создать экземпляр параметризованного объектного типа, нужно уточнить имя типа значением параметра в угловых скобках:

    stack < int > stack_of_int (50); /* Стек на 50 элементов типа int */

    stack < myClass > stmc (20); /* Стек на 20 элементов типа myClass */

В приведенном примере все компоненты-функции определены в описании класса. Когда полное определение функции-члена класса задается вне описания класса, оно должно уточняться описателем template. Например, если бы метод top_of был определен вне описания класса, определение имело бы вид:

    template < class Type >

    Type top_of ( ) { return s [ top ];}

Отметим некоторые специфические черты описаний параметризованных классов.

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

Если в параметризованном классе имеются статические (static) компоненты, то для каждого значения параметра будет использоваться свой экземпляр статической компоненты.

back.gif (1087 bytes)ind.gif (1892 bytes)next.gif (1100 bytes)
Hosted by uCoz