bigpo.ru
добавить свой файл
  1 ... 5 6 7 8
return x>y? x: y; }

Сделаем теперь функцию независимой от типов.

template<class T> T max (T x, T y) { return x>y? x: y; }

У этой функции только типовые параметры. Ключевое слово class не значит, что T должен быть пользовательским типом. Можно передавать данные встроенных типов также. (Создатели языка опять не придумали нового ключевого слова)

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

void f() {

max (1,2);

/* по параметру автоматически определяется тип шаблона.

вызовется int max<int> (1,2) */

max (‘0’,’a’); // от char

max (‘a’,100); // неоднозначность. так нельзя!!

max (2.5,1); // неоднозначность. int или double ???

Есть возможности разрешить неоднозначность:

  • явная квалификация: max<int> (‘a’,100);

  • перегрузка шаблонных функций:

int max (char c, int i) { return c>i? c: i; }

Можно перегрузить шаблон и так:

int max (int x, int y) { return x>y? x: y; }

Теперь нам непонятно, что вызывать: шаблонную функцию или явную? Модифицируем наш алгоритм поиска best matching функции, добавив шаг между 1 и 2. На первом шаге, не думая о шаблонах, ищем точное соответствие. На новом, *полуторном* шаге, пытаемся сгенерировать подходящую функцию по шаблону, чтобы получить точное соответствие. Если попытка неудачная, переходим к шагу 2 и далее выполняем алгоритм, как и раньше.

Тип параметра шаблона можно указать и явно. Эта возможность относительно новая в языке. Об этом пишет Бьярн Страуструп в интереснейшей книге ‘Дизайн и эволюция языка C++’. Однако в некоторых ситуациях не обойтись без явного указания.

Пример такой ситуации.

template<class T, class U> T convert (U u) { ... return t; };

void g (int i){

convert (i); // U = int; T – непонятно L

}

Надо учитывать, что при поиске соответствия компилятор не обращает внимания на то, чему мы присваиваем результат работы функции. Контекст не рассматривается!

Из этой ситуации можно выйти так:

convert<double> (i); // U = int; T = double

При спецификации типа указанный тип подставляется на место первого параметра, если указаны два типа – на место первого и второго, и так далее.

Мы можем придать новый смысл функции, например, заставить искать максимальный элемент в массиве. Для этого перегрузим её так:

template<class T > T max (T *p, int size) { ... };

А сможем ли мы искать с помощью нашей шаблонной функции максимум среди об’ектов класса Complex, описанного нами выше? То есть, можно ли написать так:

Complex a(1,2), b(3,4);

max (a,b); // T = Complex

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

Вообще, к сожалению, компиляторы далеко не всегда хорошо держат стандарт при работе с шаблонами.


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

Шаблоны классов тоже зачастую бывают разумными. Как правило, они применяются при описании контейнеров, то есть типов, которые содержат в себе каким-то образом структурированные об’екты других типов. Например, стек можно реализовать как контейнер. Операции над ним, вообще говоря, не зависят от типа его элементов.

Пример. Контейнер-вектор.

template<class T> class Vector {

T *p;

int size;

public: explicit Vector (int);

T& operator[] (int i);

};

Vector<int> x(20); // вектор из 20 целых чисел

Vector<Complex> y(100); // вектор из 20 комплексных чисел

Инстанцирование – процесс генерации класса по шаблону.

Описывать функции вне класса нужно так:

template<class T> T& Vector::operator[] (int i) { ... }

Пример. Класс с нетиповым параметром.

template<class T, int size> class buffer { ... }

buffer <char,1024> x;

buffer <char,512*2> y;

buffer <int,1024> z;

Возникает вопрос, какие переменные будут иметь одинаковые типы? Есть общее правило: инстанцированные классы будут считаться одинаковыми, если типовые параметры совпадают, а нетиповые равны по значению. x и z, очевидно, разного типа, так как типовые параметры не совпадают. Для нетиповых параметров должна быть определена операция сравнения на равенство. Получается, что параметры шаблона не могут быть вещественными.

/* на этом изложение теории языка C++ считается законченным. На лекциях ещё будет рассказ о STL, но это хз когда. */

Удачи всем в субботу! ;)

<< предыдущая страница