Страничка Ильи Жаркова
Статья
Главная страница Немного о себе Моя работа Мой фотоальбом Всякая всячина

Некоторые вопросы использования шаблонов

И.А. Жарков [email protected]

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

Шаблон – это механизм генерирования типов. Из определения шаблона класса и набора аргументов шаблона компилятор генерирует специализацию класса и его используемых методов. Этот процесс называется инстанцированием.

Сгенерированный по шаблону класс ведет себя, аналогично обычному классу. В частности, поддерживаются встраиваемые (inline) функции. Каждое инстанцирование класса по шаблону для заданного типа параметров приводит к появлению нового, но практически идентичного класса. Это может вызвать чрезмерное разрастание исполняемого кода и увеличить время компиляции. Создание, вместо шаблона, отдельных специализированных классов может решить только последнюю проблему. Способы борьбы с увеличением сгенерированного кода, которые Б. Страуструп описывает в своих книгах[1][2], во многих случаях помогают.

Очень часто начинающие программисты пытаются заменить шаблоны макросами, аргументируя это тем, что макросы эффективнее (ведь компилятор встраивает их в то место, где они используются), что они проще и понятнее.

Давайте рассмотрим пример, в котором исследуем объявление класса, работающего с переменной произвольного типа при использовании макроса и шаблона.

#define VALUE(valtype, valname)\

class __value##valtype##valname\

{\

private:\

valtype m_value;\

public:\

valtype Get() const { return m_value; }\

void Set(valtype val) { m_value=val; }\

};\

__value##valtype##valname valname

А теперь то же объявление, но с использованием шаблона.

template<class T> class Value

{

private:

T m_value;

public:

T Get() const { return m_value; }

void Set(T val) { m_value=val; }

};

Видно, что разница невелика. Разница невелика даже при объявлении таких объектов и их использовании с типом int:

VALUE(int, val1); // создание объекта на основе макроса

val1.Set(5);

Value<int> val2; // создание объекта на основе шаблона

Val2.Set(6);

Посмотрим, что произойдет при объявлении массива из десяти таких объектов, работающих с одинаковым типом переменных. Для макроса придется написать десять раз VALUE(int, val1);

VALUE(int, val2);

...

VALUE(int, val10);

и препроцессор создаст десять идентичных классов с именами __valueintvalX (X=1..10) и десять объектов val1…val10 соответствующих типов.

Объявление 10 переменных типа int для шаблона будет выглядеть так:

Value<int> val[10];

Будет сгенерирован один класс Value<int> и создано 10 объектов этого типа. В случае использования макросов, кроме генерации совершенно излишних определений классов, мы лишаемся возможности корректно сравнивать такие переменные и присваивать их друг другу.

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

Литература.

1.                     Страуструп Б. Язык программирования C++. М.: “Невский Диалект” - “Издательство БИНОМ”, 1999.

2.                     Страуструп Б. Дизайн и эволюция языка C++. М.: ДМК Пресс, 2000.

Хостинг любезно предоставлен ISP "Венс"

Страница была обновленна: 07.11.2002

Все замечания по содержанию сайта отправляйте по адресу [email protected]