Освой самостоятельно С++ за 21 день.
Шрифт:
2: using namespace std;
3:
4: template<class T>
5: class Print {
6: public:
7: void operator(const T& t)
8: {
9: cout << t << " ";
10: }
11: };
12:
13: int main
14: {
15: Print<int> DoPrint;
16: for (int i = 0; i < 5; ++i)
17: DoPrint(i);
18: return 0;
19: }
Результат: 0 1 2 3 4
Анализ:
Операции, не изменяющие последовательность
Операции, не изменяющие последовательность данных в структуре, реализуются с помощью таких функций, как for_each и find, search, count и т.д. В листинге 19.12 показан пример использования объекта функции и алгоритм for_each, предназначенный для печати элементов вектора.
Листинг 18.12. Использование алгоритма for_each
1: #include <iostream>
2: #include <vector>
3: #include <algorithm>
4: using namespace std;
5:
6: template<class T>
7: class Print
8: {
9: public:
10: void operator(const T& t)
11: {
12: cout << t << " ";
13: }
14: };
15:
16: int main
17: {
18: Print<int> DoPrint;
19: vector<int> vInt(5);
20:
21: for (int i = 0; i < 5; ++i)
22: vInt[i] = i * 3;
23:
24: cout << "for_each\n";
25: for_each(vInt.begin, vInt.end, DoPrint);
26: cout << "\n";
27:
28: return 0;
29: }
Результат:
for_each
0 3 6 9 12
Анализ: Обратите внимание, что все стандартные алгоритмы C++ определены в файле заголовка <algorithm>, поэтому следует включить его в нашу программу. Большая часть программы не должна вызывать никаких трудностей. В строке 25 вызывается функция for_each, чтобы опросить каждый элемент в векторе vInt. Для каждого элемента она вызывает объект функции DoPrint и передает этот элемент оператору DoPrint.operator, что приводит к выводу на экран значения данного элемента.
Алгоритмы изменения последовательности
Под изменением последовательности понимают изменение порядка элементов в структуре данных. Изменять последовательность способны операции, связанные с заполнением или переупорядочением коллекций. Алгоритм заполнения показан в листинге 19.13.
Листинг 19.13. Алгоритм изменения последовательности
1: #include <iostream>
2: #include <vector>
3: #include <algorithm>
4: using namespace std;
5:
6: template<class T>
7: class Print
8: {
9: public:
10: void operator(const T& t)
11: {
12: cout << t << " ";
13: }
14: };
15:
16: int main
17: {
18: Print<int> DoPrint;
19: vector<int> vInt(10);
20:
21: fill(vInt.begin, vInt.begin+5, 1);
22: fill(vInt.begin + 5, vInt.end, 2);
23:
24: for_each(vInt.begin, vInt.end, DoPrint);
25: cout << "\n\n";
26:
27: return 0;
28: }
Результат: 1 1 1 1 1 2 2 2 2 2
Анализ: Единственная новая деталь в этом листинге содержится в строках 21 и 22, где используется алгоритм fill. Алгоритм заполнения предназначен для заполнения элементов последовательности заданным значением. В строке 21 целое значение 1 присваивается первым пяти элементам в векторе vInt. А последним пяти элементам вектора vInt присваивается целое число 2 (в строке 22).
Резюме
Сегодня вы узнали, как создавать и использовать шаблоны — встроенное средство языка C++, используемое для создания параметризованных типов, т.е. типов, которые изменяют свое выполнение в зависимости от параметров, переданных при создании класса. Таким образом, шаблоны - это возможность многократного использования программного кода, причем безопасным и эффективным способом,
В определении шаблона устанавливается параметризованный тип, Каждый экземпляр шаблона — это реальный объект, который можно использовать подобно любому другому объекту: в качестве параметра функции, возвращаемого значения и т.д.
Классы шаблонов могут объявлять три типа функций-друзей: не относящихся к шаблону, шаблонных и специализированных по типу. В шаблоне можно объявлять статические члены. Тогда каждый экземпляр шаблона будет иметь собственный набор статических данных.
Если нужно специализировать выполнение функции шаблона в зависимости от типа, то ее можно замещать для разных типов.
Вопросы и ответы
Чем использование шаблонов лучше использования макросов?