- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
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

