Шаблоны в C++: руководство по обобщённому программированию
Шаблоны — основа обобщённого программирования, которое подразумевает написание кода независимого от конкретного типа.
Шаблон — это чертеж или формула для создания обобщённого класса или функции. Библиотечные контейнеры вроде итераторов и алгоритмов — примеры обобщённого программирования, разработанные с использованием шаблонов.
Существует единственное определение каждого контейнера, например vector, но можно определять многие разные виды векторов: vector<int> или vector<string>.
Шаблоны можно использовать для определения функций и классов. Посмотрим, как они работают.
Функциональный шаблон
Общая форма определения шаблонной функции:
template <class тип> возврат_тип имя_функции(список_параметров) {
// тело функции
}
Здесь тип — заполнитель имени типа данных, используемого функцией. Это имя можно использовать внутри определения функции.
Пример шаблонной функции, возвращающей максимум из двух значений:
Live Demo#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& Max(T const& a, T const& b) {
return a < b ? b : a;
}
int main() {
int i = 39, j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5, f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello", s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
Результат:
Max(i, j): 39 Max(f1, f2): 20.7 Max(s1, s2): World
Класс-шаблон
Как можно определять функциональные шаблоны, так можно определять класс-шаблоны. Общая форма объявления обобщённого класса:
template <class тип> class имя_класса { ... }
Здесь тип — заполнитель типа, который будет указан при инстанцировании класса. Можно определять более одного обобщённого типа через запятую.
Пример определения класса Stack<> и реализации обобщённых методов push и pop:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems; // элементы
public:
void push(T const&); // поместить элемент
void pop(); // извлечь элемент
T top() const; // вернуть верхний элемент
bool empty() const { // true если пуст
return elems.empty();
}
};
template <class T>
void Stack<T>::push(T const& elem) {
elems.push_back(elem); // добавить копию переданного элемента
}
template <class T>
void Stack<T>::pop() {
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
elems.pop_back(); // удалить последний элемент
}
template <class T>
T Stack<T>::top() const {
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
return elems.back(); // вернуть копию последнего элемента
}
int main() {
try {
Stack<int> intStack; // стек int
Stack<string> stringStack; // стек string
// работа со стеком int
intStack.push(7);
cout << intStack.top() << endl;
// работа со стеком string
stringStack.push("hello");
cout << stringStack.top() << endl;
stringStack.pop();
stringStack.pop(); // вызовет исключение
} catch (exception const& ex) {
cerr << "Exception: " << ex.what() << endl;
return -1;
}
}
Результат:
7 hello Exception: Stack<>::pop(): empty stack
Язык C
- Понимание типов данных C++: основы, модификаторы и лучшие практики
- Освоение операторов C++: полное руководство с практическими примерами
- Комментарии в C++: лучшие практики для читаемого и поддерживаемого кода
- Понимание конструкторов в C++: конструкторы по умолчанию, параметризованные и копирования
- Язык программирования C++: обзор и ключевые особенности
- Константы и литералы в C++: типы, синтаксис и лучшие практики
- Полное руководство по операторам C++: типы, использование и лучшие практики
- Работа с числовыми типами в C++: практическое руководство
- Ссылки в C++: ключевые концепции и отличия от указателей
- Препроцессор C++: как директивы формируют ваш код