ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4319
Скачиваний: 28
Глава 19. Шаблоны классов
271
int main()
{
Demo<int> d(10);
cout << add(d, d.get()) << endl; // 20
return 0;
}
Так как члены шаблона класса также являются шаблонами, то
можно определить дружественную шаблону класса функцию,
параметром которой будут различные специализации этого шаб-
лона. Пример определения такой функции
what
приведен в лис-
тинге 19.12.
В связи с этим примером отметим следующие моменты. Если па-
раметром дружественной функции являются специализации шаб-
лона класса, то для каждой специализации компилятор генериру-
ет свою дружественную функцию, хотя для этой функции и не
существует шаблона. Поэтому определять такую дружественную
функцию нужно внутри класса.
Листинг 19.12. Функция друг шаблона класса
#include <iostream>
using namespace std;
template <class T> class Demo
{
T t;
public:
Demo(T _t): t(_t) {}
friend T what(const Demo<T> &d) { return d.t; }
};
int main()
{
Demo<int> a(10);
cout << what(a) << endl; // печатает 10
Часть II. Язык программирования С++
272
Demo<double> b(5.5);
cout << what(b) << endl; // печатает 5.5
return 0;
}
К третьей группе друзей шаблона класса принадлежат шаблоны
функций и классов, которые объявлены в шаблоне класса с клю-
чевым словом
friend
, но параметры этих шаблонов не являются
параметрами шаблона рассматриваемого класса. В этом случае
говорят, что параметры друзей шаблона класса не связаны с па-
раметрами шаблона класса.
Например, в листинге 19.13 приведен пример шаблона функции,
параметром которой является тип, не являющийся параметром
шаблона класса.
Листинг 19.13. Шаблон функции друг шаблона класса
#include <iostream>
using namespace std;
template <class T> class Demo
{
int n;
T t;
public:
Demo(T _t, int _n): t(_t), n(_n) {};
T get() { return n; }
template <class S> friend S sum(Demo<S> *d, S s);
};
template <class S> S sum(Demo<S> *d, S s) { return d->n + s; }
int main()
{
Demo<int> d(10, 10);
cout << sum<double>((Demo<double>*)&d, d.get())
<< endl; // 20
return 0;
}
Глава 19. Шаблоны классов
273
19.9. Шаблоны класса
и наследование
Шаблоны классов можно использовать в построении иерархии
классов. Но в этом случае следует принимать во внимание, что
имя каждой специализации шаблона класса включает также ар-
гументы этого шаблона, заключенные в угловые скобки.
Например, в листинге 19.14 приведена иерархия классов, которая
включает шаблонные классы.
Листинг 19.14. Иерархия классов, включающая шаблонные классы
#include <iostream>
using namespace std;
template <class S, class T> struct Base
{
S s;
T t;
};
template <class S, class T, class R>
struct Derived: Base<S, T>
{
R r;
};
struct Demo: Base<int, double>
{
char* p;
};
int main()
{
Derived<int, double, char*> a;
a.s = 10;
a.t = 1.5;
a.r = "aaa";
Demo d;
d.s = 20;
Часть II. Язык программирования С++
274
d.t = 2.5;
d.p = "bbb";
Base<int, double> &b = d;
cout << b.s << ' ' << b.t << endl; // 20 2.5
return 0;
}
19.10. Шаблоны класса
как параметры шаблонов функций
Шаблон класса может быть параметром шаблона функции. На-
пример, в листинге 19.15 приведен пример определения шаблона
функции
foo
, параметром которой является шаблон класса. Заме-
тим, что параметр (тип)
S
шаблона класса, который является па-
раметром шаблона функции, используется только в списке пара-
метров шаблона и не может использоваться в заголовке или теле
функции.
Листинг 19.15. Шаблон функции, параметром которого
является шаблон класса
#include <iostream>
using namespace std;
template <class T> class Demo
{
T t;
public:
Demo(const T& _t): t(_t) {}
T foo() { return t; }
};
template <class R, template<class S> class T> R foo(Demo<T> d)
{
return d.foo();
};
Глава 19. Шаблоны классов
275
int main()
{
Demo<int> d(10);
cout << foo<int>(d) << endl; // 10
return 0;
}
Для параметров шаблона класса, который является параметром
шаблона функции, могут быть установлены значения по умолча-
нию. Например, шаблон функции
foo
из листинга 19.15 может
быть определен следующим образом:
template <class R, template<class S = int> class T> R
foo(Demo<T> d)
{
return d.foo();
};
19.11. Шаблоны класса
как параметры шаблона класса
Шаблон класса может быть также параметром шаблона класса.
Но в этом случае при определении шаблона класса запрещается
использовать ключевые слова
struct
и
union
.
Например, в листинге 19.16 приведен пример определения шаб-
лона класса
Demo
, параметром которого является шаблон класса
Box
. Как и в случае с шаблоном функции заметим, что параметр
(тип)
S
шаблона класса, который является параметром шаблона
класса, используется только в списке параметров шаблона и не
может использоваться в теле класса при определении его членов.
Листинг 19.16. Шаблон класса, параметром которого является
шаблон класса
#include <iostream>
using namespace std;