Файл: Pobegaylo_A._C_Cplus_dlya_studenta.pdf

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

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

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

Добавлен: 13.12.2020

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

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

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

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

266 

шаблона

  должен  содержать  аргументы  частичной  специализации 

шаблона класса. 
Например,  если  объявление  первичного  шаблона  класса  имеет 
вид: 

  template <class S, class T> class Demo; 

то  объявления  частичных  специализаций  этого  шаблона  могут 
иметь следующий вид: 

  template <class S, class T> class Demo<*S, T>; 
  template<class S> class Demo<S, *S>; 
  template<class S> class Demo<S, int>; 

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

частично упоря-

дочивает

 специализации шаблона класса, полученные из первич-

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


background image

Глава 19. Шаблоны классов 

267 

19.6. Статические члены  
шаблона класса 

В  шаблоне  класса  могут  быть  объявлены  статические  данные-
члены  класса.  Каждый  конкретизированный  экземпляр  шаблона 
класса имеет собственный набор таких членов. 
Если  тип  статического  атрибута  класса  является  параметром 
шаблона класса, то и сам такой атрибут является шаблоном. Так 
как  статические  атрибуты  класса  только  объявляются  внутри 
класса, то шаблон статического атрибута класса должен быть оп-
ределен  вне  шаблона  класса.  Любой  статический  член  шаблона 
класса  конкретизируется  только  в  том  случае,  если  он  реально 
используется в программе. 
В листинге 19.8 приведен пример работы со статическими члена-
ми шаблона класса. 

Листинг 19.8. Статические члены шаблона класса 

#include <iostream> 
using namespace std; 
 
template <class T> struct Demo 

  static T d; 
  static void set(T _d) { d = _d; } 
}; 
template<class T> T Demo<T>::d = 10; 
 
int main() 

  Demo<int>::d += 10; 
  cout << Demo<int>::d << endl;  // печатает 20 
  Demo<int>::set(5); 
  cout << Demo<int>::d << endl;  // печатает 5 
 
  return 0; 


background image

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

268 

19.7. Шаблоны как члены  
шаблона класса 

Шаблоны  функции  или  класса  могут  быть  членами  шаблона 
класса. Объявление шаблона-члена в шаблоне класса имеет соб-
ственные  параметры.  Для  шаблона-члена  шаблона  класса  дейст-
вуют те же правила доступа 

public

protected

 и 

private

, что и для 

других членов класса. 
Например,  в  листинге  19.9  определен  шаблон  класса,  членами 
которого являются шаблон класса и шаблон функции. 

Листинг 19.9. Шаблон класса с шаблонами-членами 

#include <iostream> 
using namespace std; 
 
template <class T1> class Demo 

  T1 d; 
public: 
  Demo(const T1& _d): d(_d) {} 
  template <class T2> struct Inner 
  { 
    T1 n; 
    T2 m; 
  }; 
  template<class T3> T3 add(T3 const &p1, T3 const &p2) 
  { 
    T3 t; 
    t = p1 + p2; 
 
    return t; 
  }; 
}; 
 
int main() 

  Demo<double> d(10.5); 


background image

Глава 19. Шаблоны классов 

269 

  Demo<int>::Inner<int> in; 
  in.n = 10; 
  in.m = 20; 
 
  int a = d.add(10,20); 
  cout << a << endl;    // 30 
 
  return 0; 

19.8. Объявление друзей  
в шаблоне класса 

В шаблоне класса можно объявить друзей шаблона класса. После 
конкретизации шаблона класса эти друзья станут друзьями полу-
ченной  специализации  шаблона  класса.  Друзей  шаблона  класса 
можно разбить на три группы: 

 

друзья шаблона класса, которые не являются шаблонами; 

 

друзья шаблона класса, которые сами являются шаблонами, и 
их параметры связаны с параметрами шаблона класса; 

 

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

К  первой  группе  друзей  шаблона  класса  принадлежат  обычные 
функции и классы, которые объявлены в шаблоне класса с клю-
чевым словом 

friend

В  листинге  19.10  приведен  пример  функции 

what

,  объявленной 

другом шаблона класса 

Demo

Листинг 19.10. Функция-друг шаблона класса 

#include <iostream> 
using namespace std; 
 
template <class T> class Demo 

  static int n; 


background image

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

270 

public: 
  const T& foo(const T& t) { return t; } 
  friend int what() { return 10; } 
}; 
template<class T> int Demo<T>::n = 10; 
 
int main() 

  Demo<int> d; 
  cout << what() << endl;     // печатает 10 
  cout << d.foo(20) << endl;  // печатает 20 
 
  return 0; 

Ко второй группе друзей шаблона класса принадлежат шаблоны 
функций и классов, которые объявлены в шаблоне класса с клю-
чевым словом 

friend

, и параметры этих шаблонов являются так-

же  параметрами  шаблона  рассматриваемого  класса.  В  этом  слу-
чае говорят, что параметры друзей шаблона класса связаны с па-
раметрами шаблона класса. 
Например, в листинге 19.11 приведен пример шаблона функции, 
параметром которой является параметр-тип шаблона класса. 

Листинг 19.11. Шаблон функции-друга шаблона класса 

#include <iostream> 
using namespace std; 
 
template <class T> class Demo 

  T t; 
public: 
  Demo(T _t): t(_t) {}; 
  T get() { return t; } 
  template <class T> friend T add(Demo<T> &d, T t); 
}; 
template <class T> T add(Demo<T> &d, T t) { return d.t + t; } 


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