Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Вопрос 1.16. Макросы и шаблоны функций. Отличия, плюсы и минусы. Примеры.




Иногда может показаться, что сильно типизированный язык создает препятствия для реализации совсем простых функций. Например, хотя следующий алгоритм функции min() тривиален, сильная типизация требует, чтобы его разновидности были реализованы для всех типов, которые мы собираемся сравнивать:

int min(int a, int b) { return a < b? a: b;} double min(double a, double b) {
return a < b? a: b;
}

Заманчивую альтернативу явному определению каждого экземпляра функции min() представляет использование макросов, расширяемых препроцессором

Макросы позволяют заменить большой тект коротким именем макроса. Позволяются также макросы с параметрами. При этом в отличие от функций с атрибутом inline, проверки типов аргументов не выполняется, а тело макроса может быть сколь угодно сложным. Подстановка выполняется на стадии компиляции. Макросы являются наследием языка С, и в С++ обычно заменяются безопасными возможностями языка как шаблоны, inline функции, перечисления enum, переопределение типов typedef.

Макросы определяются командой препроцессора #define и отменяются командой #undefine. Для продолжения макроса на другой строке используется символ \\.

:

#define min(a, b) ((a) < (b)? (a): (b))

Но этот подход таит в себе потенциальную опасность. Определенный выше макрос правильно работает при простых обращениях к min(), например:

min(10, 20);min(10.0, 20.0);

но может преподнести сюрпризы в более сложных случаях: такой механизм ведет себя не как вызов функции, он лишь выполняет текстовую подстановку аргументов. В результате значения обоих аргументов оцениваются дважды: один раз при сравнении a и b, а второй – при вычислении возвращаемого макросом результата:

#include <iostream>#define min(a,b) ((a) < (b)? (a): (b)) const int size = 10;
int ia[size]; int main() {
int elem_cnt = 0;
int *p = &ia[0]; // подсчитать число элементов массива
while (min(p++,&ia[size])!= &ia[size])
++elem_cnt; cout << "elem_cnt: " << elem_cnt
<< "\texpecting: " << size << endl;
return 0;
}

На первый взгляд, эта программа подсчитывает количество элементов в массиве ia целых чисел. Но в этом случае макрос min() расширяется неверно, поскольку операция постинкремента применяется к аргументу-указателю дважды при каждой подстановке. В результате программа печатает строку, свидетельствующую о неправильных вычислениях:

elem_cnt: 5 expecting: 10

Шаблоны функций предоставляют в наше распоряжение механизм, с помощью которого можно сохранить семантику определений и вызовов функций (инкапсуляция фрагмента кода в одном месте программы и гарантированно однократное вычисление аргументов), не принося в жертву сильную типизацию языка C++, как в случае применения макросов.
Шаблон дает алгоритм, используемый для автоматической генерации экземпляров функций с различными типами. Программист параметризует все или только некоторые типы в интерфейсе функции (т.е. типы формальных параметров и возвращаемого значения), оставляя ее тело неизменным. Функция хорошо подходит на роль шаблона, если ее реализация остается инвариантной на некотором множестве экземпляров, различающихся типами данных, как, скажем, в случае min().
Так определяется шаблон функции min():

template <class Type> Type min2(Type a, Type b) { return a < b? a: b;}int main() {
// правильно: min(int, int);
min(10, 20); // правильно: min(double, double);
min(10.0, 20.0);
return 0;
}

Если вместо макроса препроцессора min() подставить в текст предыдущей программы этот шаблон, то результат будет правильным:

elem_cnt: 10 expecting: 10


Как объявление, так и определение шаблона функции всегда должны начинаться с ключевого слова template, за которым следует список разделенных запятыми идентификаторов, заключенный в угловые скобки '<' и '>', – список параметров шаблона, обязательно непустой. У шаблона могут быть параметры-типы, представляющие некоторый тип, и параметры-константы, представляющие фиксированное константное выражение.

 






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных