Kniga-Online.club
» » » » Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Читать бесплатно Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп. Жанр: Программирование год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:
class="code">  int size() const { return sz; }

  int capacity() const { return space; }

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

  void push_back(double d);

  void reserve(int newalloc);

};

Обратите внимание на то, что этот класс содержит все основные операции (см. раздел 18.3): конструктор, конструктор по умолчанию, копирующий конструктор, деструктор. Он также содержит операции для доступа к данным (индексирование []), получения информации об этих данных (size() и capacity()), а также для управления ростом вектора (resize(), push_back() и reserve()).

19.3. Шаблоны

Однако нам мало иметь вектор, состоящий из чисел типа double; мы хотим свободно задавать тип элементов наших векторов. Рассмотрим пример.

vector<double>

vector<int>

vector<Month>

vector<Window*>          // вектор указателей на объекты класса Window

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

vector<char>

 

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

 

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

19.3.1. Типы как шаблонные параметры

 

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

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

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

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

vector<int> vi;            // T — int

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

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

 

 Можно просто считать, что компилятор генерирует класс конкретного типа (соответствующего шаблонному аргументу), подставляя его вместо шаблонного параметра. Например, когда компилятор видит в программе конструкцию 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>).

 

 Иногда шаблонный класс называют порождающим типом (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

Перейти на страницу:

Бьёрн Страуструп читать все книги автора по порядку

Бьёрн Страуструп - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


Программирование. Принципы и практика использования C++ Исправленное издание отзывы

Отзывы читателей о книге Программирование. Принципы и практика использования C++ Исправленное издание, автор: Бьёрн Страуструп. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*