Глава 4. Препроцессор __ ___________________________81
классами себя давно изжила, а сам препроцессор ныне занял более традиционное и свойственное ему место.
Но, как оказалось, это был не последний случай использования препроцессора для создания механизмов, прижившихся и ставших впоследствии неотъемлемой частью языка. Вновь в этом качестве он пригодился при реализации шаблонов.
Реализация шаблонных классов и функций
Шаблонными (template) или родовыми (generic) классами 'и функциями называются такие классы и функции, реализация которых логически независима от типа данных, к которым они применяются. Примером шаблонной функции может служить быстрая сортировка. Спросите себя: можно ли представить себе функцию быстрой сортировки, не привязанную к типу сортируемых данных? Разумеется можно, ведь .фактически, не считая операции вычитания сортируемых данных, вся сортировка представляет из себя всего-навсего вложенный цикл for.
То же самое можно сказать о классе ограниченных массивов. Опять-таки задайтесь вопросом, могут ли существовать массивы для разных типов данных и только ли типом данных они отличаются? Снова ответ будет утвердительным, следовательно, массив можно преобразовать в параметризованный класс. Шаблоны (называемые иногда также параметризованными типами) как раз и призваны удовлетворить потребность в отделении реализации от типа данных. Они введены в Borland C++ начиная с версии З.х.
Сейчас шаблоны стали полноправной частью C++, а впервые они заявили о себе как о жизнеспособной конструкции, будучи реализованными посредством препроцессора. В качестве несложного примера можно привести функцию, обменивающую значениями две переменные одного типа. На псевдокоде алгоритм условно можно записать следующим образом:
Взять две переменные х и у, присвоить значение х временной переменной того же типа, присвоить у переменной х, завершить перестановку присваиванием у значения временной переменной.
Для типа char функция swap будет выглядеть так:
inline void Swap( chars x, chars у) { char t = х; х = у; у = t; }
Примечание
[Ключевое слово inline здесь не обязательно. Оно указывает компилятору, что в исполняемый код желательно включать не вызов, а целиком тело этой функции.
Приведенное решение будет в точности таким же для перестановки и чисел с плавающей запятой, и дат, и так далее. Вся разница между ними будет