Jenter Алекс
Шрифт:
ASSERT_KINDOF полностью идентичен следующей конструкции (для нашего примера):
Для того, чтобы получить информацию о классе в процессе исполнения, этот класс должен быть унаследован от CObject (или одного из его потомков), и для него должны быть использованы макросы DECLARE_DYNAMIC(classname) и IMPLEMENT_DYNAMIC(classname, baseclass) (иначе обращение к ASSERT_KINDOF приведет к ошибке нарушения защиты). Это относится и к проверяемому объекту, и к классу.
ASSERT_VALID служит для проверки внутреннего состояния объектов. Этот макрос принимает один параметр – указатель на проверяемый объект – и проделывает с ним следующее: проверяет валидность указателя, проверяет его на равенство NULL, и вызывает функцию объекта AssertValid.
AssertValid реализована почти во всех классах MFC (унаследованных от CObject), но разработчик может реализовать ее и в своем классе, соблюдая определенные правила. Во-первых, AssertValid должна быть переопределенной виртуальной функцией класса CObject. Эта функция описана как const, поэтому внутри нее нельзя изменять данные класса. Во-вторых, для индикации факта невалидности объекта функция должна использовать макрос ASSERT. И в-третьих, в AssertValid желательно вызвать эту же функцию класса-родителя.
Таким образом, разработчик может использовать ASSERT_VALID для реализации любых алгоритмов проверки состояния объекта. Например, вот так:
ПРИМЕЧАНИЕ
ASSERT_KINDOF и ASSERT_VALID развернутся в код только при Debug-сборке.
В MFC определены два вспомогательных макроса для тестирования указателей: ASSERT_POINTER и ASSERT_NULL_OR_POINTER. Оба они принимают в качестве параметров два значения — указатель и его тип. ASSERT_POINTER сначала проверяет указатель на NULL, затем тестирует память по этому указателю на валидность. По непрохождении хотя бы одной проверки макрос срабатывает и останавливает работу программы. ASSERT_NULL_OR_POINTER также проверяет память, на которую ссылается указатель, но не прерывает выполнение программы, если тестируемый указатель равен NULL (хотя указатель при этом и является невалидным).
При отладке приложений у разработчика часто возникает необходимость узнать значение какой-нибудь переменной или результат, возвращенный функцией. Для этого используют либо пошаговое исполнение интересующего участка кода с просмотром переменных в Watch-окне отладчика, либо вывод информации с помощью информационных окон (функции MessageBox и AfxMessageBox).
В Windows предусмотрен еще один способ получить информацию от программы во время ее исполнения – функция OutputDebugString. Функция принимает LPCTSTR-строку и посылает ее отладчику, под управлением которого исполняется приложение. В случае запуска приложения из Visual C++ посланная строка попадает в окно Output последнего (закладка Debug). Преимущество данного способа в том, что он не требует прерывать работу программы для отслеживания значений (что иногда критично – например, при отлаживании обработчика сообщения WWM_TIMER или асинхронного выполнения функций), и не требует убирать лишний код после отлаживания нужного участка (в отличие, скажем, от метода с MessageBox).
OutputDebugString можно использовать следующим образом:
MFC упрощает вывод отладочной информации, определяя глобальный объект afxDump класса CDumpContext. Информация при этом выводится таким образом:
Отладочную информацию можно также выводить макросами TRACE, TRACE0, TRACE1, TRACE2 и TRACE3 (для таких целей обычно их и используют). Все они выводят переданную им информацию через afxDump, при этом принимают те же параметры, что и функция printf:
Макросы TRACEn аналогичны макросу TRACE, с той лишь разницей, что их первый параметр имеет тип LPCSTR (а не LPCTSTR), и они принимают не произвольное число параметров, а определенное цифрой в их имени. Длина первого параметра всех TRACE-макросов (после всех подстановок) не должна превышать 512 символов, иначе макрос сгенерирует ASSERT.