ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4321
Скачиваний: 28
Глава 19. Шаблоны классов
261
cout << n << endl;
cout << s.isEmpty() << ' ' << s.isFull() << endl;
return 0;
}
В отличие от шаблонов функций, шаблоны классов могут иметь
значения параметров, заданные по умолчанию. Это относится как
к параметрам типам, так и к параметрам не типам. Если шаблон
класса имеет значения параметров, заданные по умолчанию, то
при конкретизации этого шаблона класса такие параметры можно
опустить. Если для некоторого параметра шаблона класса задано
значение по умолчанию, то значения по умолчанию должны быть
заданы и для всех последующих параметров шаблона.
Например, шаблон класса
Box
можно объявить следующим об-
разом:
template <class T = int> class Box;
Тогда, если при конкретизации шаблона класса
Box
не указать его
параметр-тип, то по умолчанию будет конкретизироваться класс
для хранения целого числа.
В листинге 19.5 показан пример конкретизации шаблона класса
Box
, параметр
T
которого по умолчанию имеет значение
int
.
Листинг 19.5. Конкретизация шаблона класса
Box
со значением параметра, заданным по умолчанию
#include "Box.h"
#include <iostream>
using namespace std;
int main()
{
Box<> n;
n.put(10);
cout << n.isEmpty() << endl;
cout << n.get() << endl;
cout << n.isEmpty() << endl;
Часть II. Язык программирования С++
262
return 0;
}
В отличие от шаблона функции шаблон класса конкретизируется
только при определении объекта класса. При объявлении ссылок
и указателей на класс шаблон класса не конкретизируется, т. к.
в этом случае объект класса может и не существовать.
По определению считается, что функция-член шаблона класса
сама является шаблоном. Стандарт языка программирования C++
требует, чтобы она конкретизировалась только при вызове или
при получении ее адреса. Поэтому при конкретизации шаблона
класса компилятор генерирует код только тех функций-членов
класса, которые явно или неявно вызываются в программе.
Способность компилятора генерировать из шаблона класса опре-
деления различных классов в соответствии с аргументами-типами
шаблона называется
параметрическим
(parametric)
полиморфиз-
мом
.
19.3. Использование
ключевого слова
typename
Ключевое слово
typename
может использоваться в списке пара-
метров шаблона для задания параметра типа вместо ключевого
слова
class
. Кроме этого, ключевое слово
typename
может также
использоваться в теле шаблона, чтобы указать компилятору на
то, что идентификатор является типом. То есть в теле шаблона
ключевое слово
typename
нужно использовать всегда, когда иден-
тификатор является именем типа и квалифицируется именем па-
раметра-типа шаблона или именем шаблона класса. В этом слу-
чае имена типов должны иметь следующий вид:
typename имя_параметра_типа::имя_типа
или
typename имя_шаблона_класса::имя_типа
В листинге 19.6 приведен пример использования ключевого сло-
ва
typename
в определении шаблона класса
Demo
. Если в этом слу-
Глава 19. Шаблоны классов
263
чае ключевое слово
typename
опустить, то компилятор не сможет
определить смысл идентификатора
T::Inner
.
Листинг 19.6. Использование ключевого слова
typename
в определении класса
#include <iostream>
using namespace std;
template <class T> struct Demo
{
typename T::Inner* s; // уточняем, что T::Inner – это тип
int what() { return s->n; }
};
struct Outer
{
struct Inner
{
int n;
};
};
int main()
{
Outer::Inner s;
s.n = 10;
Demo<Outer> d;
d.s = &s;
cout << d.what() << endl; // печатает 10
return 0;
}
В заключение этого раздела отметим, что в принципе компилятор
может определить смысл любого идентификатора в шаблоне при
конкретизации этого шаблона. Поэтому часто при отсутствии
ключевого слова
typename
компилятор все равно верно определя-
ет смысл идентификатора, которому по стандарту должно пред-
шествовать это ключевое слово. Однако такое поведение компи-
лятора не предусмотрено стандартом языка программирова-
ния C++.
Часть II. Язык программирования С++
264
19.4. Явная специализация
шаблона класса
Явной специализацией
шаблона класса называется определение
шаблона класса для конкретных значений всех параметров этого
шаблона. Явная специализация шаблона класса имеет следующий
синтаксис:
template<>
class|struct|union имя_класса<список_аргументов_шаблона>
блок_класса
где
имя_класса
задает имя шаблона класса, а в угловых скобках
указан список аргументов шаблона, для которых выполняется
явная специализация этого шаблона класса.
Явная специализация шаблона класса используется в тех же слу-
чаях, что и явная специализация шаблонов функций, а именно
если:
какой-то тип данных не может быть параметром шаблона
класса в силу невозможности такой реализации этого шабло-
на, которая была бы совместима с другими типами данных;
специальная реализация шаблона класса для какого-то типа
данных более эффективна, чем общая реализация шаблона.
В листинге 19.7 приведен пример явной специализации шаблона
класса.
Листинг 19.7. Явная специализация шаблона класса
#include <iostream.h>
#include <string.h>
template <class T> class Demo
{
T t;
public:
Demo(T _t): t(_t) {}
T max(T _t) { return t > _t ? t : _t; }
};
Глава 19. Шаблоны классов
265
// явная специализация шаблона для строк
template<> class Demo<char*>
{
char* t;
public:
Demo(char* _t) { t = new char[strlen(_t) + 1]; strcpy(t,
_t); }
char* max(char* _t) { return strcmp(t, _t) > 0 ? t : _t; }
};
int main()
{
Demo<int> d(10);
cout << d.max(20) << endl; // печатает: 20
Demo<char*> s("aaa");
cout << s.max("bbb") << endl; // печатает: bbb
return 0;
}
19.5. Частичная специализация
шаблона класса
Шаблон класса, как он был определен в начале этой главы, назы-
вается
первичным
шаблоном класса. Шаблон класса можно спе-
циализировать для одного или нескольких параметров, оставляя
другие параметры неспециализированными. Такая специализация
шаблона класса называется
частичной
. Определение частичной
специализации шаблона класса имеет следующий синтаксис:
template<список_параметров_шаблона>
class|struct|union имя_класса<список_аргументов_шаблона>
блок_класса
где
имя_класса
должно совпадать с именем первичного шаблона
класса,
список_параметров_шаблона
должен быть подсписком спи-
ска параметров первичного шаблона класса,
список_аргументов_