Файл: Pobegaylo_A._C_Cplus_dlya_studenta.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.12.2020

Просмотров: 4321

Скачиваний: 28

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Глава 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; 


background image

Часть II. Язык программирования С++ 

262 

  return 0; 

В отличие от шаблона функции шаблон класса конкретизируется 
только при определении объекта класса. При объявлении ссылок 
и  указателей  на  класс  шаблон  класса  не  конкретизируется,  т. к. 
в этом случае объект класса может и не существовать. 
По  определению  считается,  что  функция-член  шаблона  класса 
сама является шаблоном. Стандарт языка программирования C++ 
требует,  чтобы  она  конкретизировалась  только  при  вызове  или 
при  получении  ее  адреса.  Поэтому  при  конкретизации  шаблона 
класса  компилятор  генерирует  код  только  тех  функций-членов 
класса, которые явно или неявно вызываются в программе. 
Способность компилятора генерировать из шаблона класса опре-
деления различных классов в соответствии с аргументами-типами 
шаблона  называется 

параметрическим

  (parametric) 

полиморфиз-

мом

19.3. Использование  
ключевого слова 

typename

 

Ключевое  слово 

typename

  может  использоваться  в  списке  пара-

метров  шаблона  для  задания  параметра  типа  вместо  ключевого 
слова 

class

. Кроме этого, ключевое слово 

typename

  может  также 

использоваться  в  теле  шаблона,  чтобы  указать  компилятору  на 
то,  что  идентификатор  является  типом.  То  есть  в  теле  шаблона 
ключевое слово 

typename

 нужно использовать всегда, когда иден-

тификатор является именем типа и квалифицируется именем па-
раметра-типа  шаблона  или  именем  шаблона  класса.  В  этом  слу-
чае имена типов должны иметь следующий вид: 

  typename имя_параметра_типа::имя_типа 

или 

  typename имя_шаблона_класса::имя_типа 

В листинге 19.6 приведен пример использования ключевого сло-
ва 

typename

 в определении шаблона класса 

Demo

. Если в этом слу-


background image

Глава 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++. 


background image

Часть 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; } 
}; 


background image

Глава 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 имя_класса<список_аргументов_шаблона> 
  блок_класса 

где 

имя_класса

  должно  совпадать  с  именем  первичного  шаблона 

класса, 

список_параметров_шаблона

  должен  быть  подсписком спи-

ска  параметров  первичного  шаблона  класса, 

список_аргументов_ 


Смотрите также файлы