Читаем Программирование полностью

vector< vector > // вектор векторов из объектов класса Record

vector

  Для этого мы должны научиться определять шаблоны. На самом деле мы с самого начала уже использовали шаблоны, но до сих пор нам не приходилось определять их самостоятельно. Стандартная библиотека содержит все необходимое, но мы не должны полагаться на готовые рецепты, поэтому следует разобраться, как спроектирована и реализована стандартная библиотека, например класс vector и функция sort() (разделы 21.1 и Б.5.4). Это не просто теоретический интерес, поскольку, как обычно, средства и методы, использованные при создании стандартной библиотеки, могут помочь при работе над собственными программами. Например, в главах 21-22 мы покажем, как с помощью шаблонов реализовать стандартные контейнеры и алгоритмы, а в главе 24 продемонстрируем, как разработать класс матриц для научных вычислений.

  По существу, шаблон (template) — это механизм, позволяющий программисту использовать типы как параметры класса или функции. Получив эти аргументы, компилятор генерирует конкретный класс или функцию. 

<p id="AutBody_Root350"><strong>19.3.1. Типы как шаблонные параметры</strong></p>

  Итак, мы хотим, чтобы тип элементов был параметром класса vector. Возьмем класс vector и заменим ключевое слово double буквой T, где T — параметр, который может принимать значения, такие как double, int, string, vector и Window*. В языке С++ для описания параметра T, задающего тип, используется префикс template, означающий “для всех типов T”.

Рассмотрим пример.

// почти реальный вектор элементов типа T

template class vector {

  // читается как "для всех типов T" (почти так же, как

  // в математике)

  int sz;      // размер

  T* elem;     // указатель на элементы

  int space;   // размер + свободная память

public:

  vector():sz(0),elem(0),space(0) { }

  explicit vector(int s);

  vector(const vector&);            // копирующий конструктор

  vector& operator=(const vector&); // копирующее присваивание

  ~vector() { delete[] elem; }      // деструктор

  T& operator[](int n) { return elem[n]; } // доступ: возвращает

                                           // ссылку

  const T& operator[](int n) const { return elem[n]; }

  int size() const { return sz; }   // текущий размер

  int capacity() const { return space; }

  void resize(int newsize);         // увеличивает вектор

  void push_back(const T& d);

  void reserve(int newalloc);

};

Это определение класса vector совпадает с определением класса vector, содержащего элементы типа double (см. раздел 19.2.6), за исключением того, что ключевое слово double теперь заменено шаблонным параметром T. Этот шаблонный класс vector можно использовать следующим образом:

vector vd;         // T — double

vector vi;            // T — int

vector vpd;       // T — double*

vector< vector > vvi; // T — vector, в котором T — int 

  Можно просто считать, что компилятор генерирует класс конкретного типа (соответствующего шаблонному аргументу), подставляя его вместо шаблонного параметра. Например, когда компилятор видит в программе конструкцию vector, он генерирует примерно такой код:

class vector_char {

  int sz;      // размер

  char* elem;  // указатель на элементы

  int space;   // размер + свободная память

public:

  vector_char();

  explicit vector_char(int s);

  vector_char(const vector_char&);  // копирующий конструктор

  vector_char& operator=(const vector_char &); // копирующее

                                               // присваивание

  ~vector_char ();            // деструктор

  char& operator[] (int n);   // доступ: возвращает ссылку

  const char& operator[] (int n) const;

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже