Литмир - Электронная Библиотека
A
A

  ~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<double> vd;         // T — double

vector<int> vi;            // T — int

vector<double*> vpd;       // T — double*

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

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Можно просто считать, что компилятор генерирует класс конкретного типа (соответствующего шаблонному аргументу), подставляя его вместо шаблонного параметра. Например, когда компилятор видит в программе конструкцию
vector<char>
, он генерирует примерно такой код:

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;

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

  int capacity() const;

  void resize(int newsize);   // увеличение

  void push_back(const char& d);

  void reserve(int newalloc);

};

Для класса

vector<double>
компилятор генерирует аналог класса
vector
, содержащий элементы типа
double
(см. раздел 19.2.6), используя соответствующее внутреннее имя, подходящее по смыслу конструкции
vector<double>
).

 

Программирование. Принципы и практика использования C++ Исправленное издание - _002.png
 Иногда шаблонный класс называют порождающим типом (type generator). Процесс генерирования типов (классов) с помощью шаблонного класса по заданным шаблонным аргументам называется специализацией (specialization) или конкретизацией шаблона (template instantiation). Например, классы
vector<char>
и
vector<Poly_line*>
называются специализациями класса
vector
. В простых ситуациях, например при работе с классом
vector
, конкретизация не вызывает затруднений. В более общих и запутанных ситуациях конкретизация шаблона очень сильно усложняется. К счастью для пользователей шаблонов, вся эта сложность обрушивается только на разработчика компилятора.

Конкретизация шаблона (генерирование шаблонных специализаций) осуществляется на этапе компиляции или редактирования связей, а не во время выполнения программы.

Естественно, шаблонный класс может иметь функции-члены. Рассмотрим пример.

void fct(vector<string>& v)

{

  int n = v.size();

  v.push_back("Norah");

  // ...

}

При вызове такой функции-члена шаблонного класса компилятор генерирует соответствующую конкретную функцию. Например, когда компилятор видит вызов

v.push_back("Norah"), он генерирует функцию

void vector<string>::push_back(const string& d) { /* ... */ }

используя шаблонное определение

template<class T> void vector<T>::push_back(const T& d) { /* ... */ };

Итак, вызову

v.push_back("Norah")
соответствует конкретная функция. Иначе говоря, если вам нужна функция с конкретным типом аргумента, компилятор сам напишет ее, основываясь на вашем шаблоне.

Вместо префикса

template<class T>
можно использовать префикс
template <typename T>
. Эти две конструкции означают одно и то же, но некоторые программисты все же предпочитают использовать ключевое слово
typename
, “потому, что оно яснее, и потому, что никто не подумает, что оно запрещает использовать встроенные типы, например тип
int
, в качестве шаблонного аргумента”. Мы считаем, что ключевое слово
class
уже означает “тип”, поэтому никакой разницы между этими конструкциями нет. Кроме того, слово
class
короче.

257
{"b":"847443","o":1}