Глава 11. Функции_____________________________________271
Макрос a3sert, определенный в файле assert, h, позволяет производить проверку инвариантов. Этот макрос требует логического или целочисленного аргумента — любого, который можно проверить на истинность. Истинным считается ненулевое значение, а нулевое, соответственно, ложным.
Допустим, имеется функция, копирующая строку
void CopyStringf char *dst, const char *src)
{
// Если строка нулевая, программа завершается
assert( src Т = 0) ;
dst = strdup( src) ;
}
Наше утверждение приводит к тому, что функция copystring, получив нулевую исходную строку, аварийно завершается. При этом выводится номер строки, имя модуля и краткое сообщение, После чего завершается и сама программа (все эти действия производит макрос assert).
В готовой программе утверждений присутствовать не должно — они включаются только для проверки и отладки. Однако нет нужды удалять их из текста программ, достаточно просто поместить перед каждой строкой, включающей заголовок assert.h, директиву препроцессора:
ftdefine NDEBUG
Совет
Отладочный код ни в коем случае не должен вмешиваться в управление программой. Если он станет как-либо изменять ход программы, то поведение ее будет зависеть от наличия или отсутствия отладочного кода.
Кроме того, отладочный код не должен подменять собой нормальный контроль ошибок во время выполнения — в противном случае после отключения отладочных механизмов пользователи ваших программ останутся беззащитными. В основном проверки во время выполнения распространяются на предельные значения и тому подобные вещи. В современную доктрину защиты от ошибок также входит обработка исключительных ситуаций (exception handling), о которой можно подробнее прочитать в главе 22 "Обработка исключительных ситуаций".
Главное — не забывайте добавлять отладочный код во время написания функций. Таким образом вы сможете обрести спокойствие как за свои функции, так и за ожидаемые результаты.
Почему у функций C++ меньше аргументов
C++ является языком объектно-ориентированного программирования. Это означает, в частности, что данные и функции в классах связаны друг с другом (о чем подробнее будет рассказано в главе 15 "Перегрузка функций").