C++ 3d.Комментарии


Макросы


В C++ макросы не нужны! До боли знакомое высказывание, не так ли? Я бы его немного уточнил: не нужны, если вы не хотите существенно облегчить себе жизнь.

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

Итак, когда макросы могут принести пользу?

  1. Макрос как надъязыковое средство. Хороший примером является простой, но удивительно полезный отладочный макрос _VAL_, выводящий имя и значение переменной: #define _VAL_(var) #var "=" << var << " "

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

  • Информация о текущем исходном файле и строке -- ее пользу при отладке трудно переоценить. Для этого я использую специальный макрос _ADD_. Например: cout<<_ADD_("Ошибка чтения");

    выведет что-то вроде Ошибка чтения <file.cpp:34>

    А если нужен перевод строки, то стоит попробовать cout<<"Ошибка чтения" _ADD_("") "\n";

    Такой метод работает, потому что макрос _ADD_ возвращает строковый литерал. Вроде бы эквивалентная функция char* _ADD_(char*);

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

  • Рассмотрим устройство _ADD_: #define _ADD_tmp_tmp_(str,arg) str " <" __FILE__ ":" #arg ">" #define _ADD_tmp_(str,arg) _ADD_tmp_tmp_(str,arg) #define _ADD_(str) _ADD_tmp_(str,__LINE__)

    Почему все так сложно? Дело в том, что __LINE__ в отличие от __FILE__ является числовым, а не строковым литералом и чтобы привести его к нужному типу придется проявить некоторую смекалку. Мы, конечно, не можем написать: #define _ADD_(str) str " <" __FILE__ ":" #__LINE__ ">"




    - Начало -  - Назад -  - Вперед -