Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Классы CDumpContext и CObject
Если оператор вставки класса CDumpContext принимает указатели и ссылки на CObject, он должен также принимать указатели и ссылки на производные от него классы. Рассмотрим тривиальный класс CAction, производный от CObject: class CAction : public CObject { public: int m_nTime; };
Что же происходит при выполнении следующего оператора? #ifdef _DEBUG afxDump << action; // action – объект класса CAction #endif // _DEBUG
Происходит вот что. Вызывается виртуальная функция CObject::Dump(). Если Вы не переопределили ее для CAction, то многого от нее не получите — разве что адрес объекта. Однако, переопределив Dump, можно вывести внутреннее состояние интересующего нас объекта. Посмотрим на функцию CAction::Dump(): #ifdef _DEBUG void CAction::Dump(CDumpContext& dc) const { CObject::Dump(dc); // всегда вызывайте функцию базового класса dc << "time = " << m_nTime << "\n"; } #endif // _DEBUG
Функция Dump базового класса CObject выводит строку наподобие следующей: a CObject at $4498
Если в определении класса CAction использован макрос DECLARE_DYNAMIC, а в реализации — IMPLEMENT_DYNAMIC, то при выводе диагностической информации Вы получите имя данного класса: a CAction at $4498
даже если оператор отладочного вывода выглядит так: #ifdef _DEBUG afxDump << (CObject&) action; #endif // _DEBUG
Вместе эти два макроса вставляют в ваш класс, производный от CObject, специальный код библиотеки MFC периода выполнения. При наличии такого кода программа в период выполнения может определить имя класса объекта (например, для отладочного вывода) и получить информацию об иерархии классов.
Макрос ASSERT
ASSERT(выражение булевского типа);
Этот макрос рекомендуется использовать для обнаружения ошибок на этапе разработки программы. Параметр макроса – выражение булевского типа – должен быть выбран так, чтобы его истинное значение соответствовало нормальной работе программы. Если это значение истина, то ничего не происходит, а если оно ложно, то выводится – в отдельном окне – сообщение и работа программы прерывается. В окне сообщения указывается имя программы, имя исходного файла и номер строки в этом файле, в которой записан макрос. Окно также имеет три кнопки: Abort – прервать выполнение программы; Retry – перейти к отладке программы не прерывая ее выполнение; Ignore – игнорировать ошибку и продолжать выполнение программы.
Следующий пример показывает, как можно использовать макрос для проверки значения, возвращаемого некоторой функцией: int x = SomeFunc(y); ASSERT(x >= 0); // программа прерывается, если значение х отрицательно
Обсуждаемый макрос также может быть использован в комбинации с функцией CObject::IsKindOf(), которая возвращает значение TRUE, если вызвавший ее объект принадлежит классу-параметру этой функции или является наследником класса-параметра, например:
// пример для CObject::IsKindOf CAge a(21); /* предполагается, что класс CAge объявлен как наследник класса CObject */ ASSERT( a.IsKindOf( RUNTIME_CLASS( CAge ) ) ); ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );
Систематическое использование макроса в программе помогает отлавливать ошибки во время разработки. Хорошей идеей является применение макроса во всех случаях, когда можно сделать какие-либо правдоподобные суждения о значениях тех или иных величин или выражений. Например, если Вы предполагаете, что некоторый параметр не является нулевым, используйте макрос ASSERT для проверки своей гипотезы. Макрос ASSERT отлавливает ошибки только в том случае, если используются отладочные версии библиотеки MFC. В противном случае макрос «не работает» и не продуцирует никакого программного кода. Если же Вы хотите, чтобы выражение вычислялось в обоих версиях программы – отладочной и окончательной, – используйте макрос VERIFY вместо ASSERT. В отладочной версии макрос VERIFY ведет себя так же, как и макрос ASSERT. В окончательной версии макрос VERIFY вычисляет выражение, но не проверяет результат. Макрос _ASSERTE ведет себя так же, как и макрос ASSERT, но выводит также в окно и выражение, переданное ему в качестве параметра. Макрос ASSERT_VALID
ASSERT_VALID(pObject)
Этот макрос можно использовать для проверки состояния объекта, указатель на который передан макросу в качестве параметра. Параметр pObject должен быть указателем на класс, производный от CObject и имеющий переопределенную версию член-функции AssertValid(). Макрос обеспечивает вызов функции AssertValid(), передавая ей pObject в качестве параметра. В окончательной версии (Release version) программы этот макрос не делает ничего, а в отладочной он проверяет неравенство pObject!=NULL и уже затем вызывает AssertValid(). В случае обнаружения некорректности объекта выводится окно с сообщением об ошибке так же, как и в случае использования ASSERT. Макрос можно использовать только в приложении с поддержкой MFC. Пример: CAXServSrvrItem* pItem = new CAXServSrvrItem(this); ASSERT_VALID(pItem); Макрос VERIFY
VERIFY(выражение булевского типа);
В отладочной версии этот макрос ведет себя так же, как и макрос ASSERT. В окончательной версии этот макрос вычисляет значение выражения, в отличие от ASSERT, но не проверяет его и не продуцирует каких-либо действий. Таким образом, макрос VERIFY следует использовать тогда, когда, например, при вычислении выражения происходит вызов функции, который должен иметь место и в окончательной версии программы. Автоматическая диагностика неуничтоженных объектов
Если при сборке программы выбрана конфигурация Debug, после завершения программы каркас приложений сообщает обо всех неуничтоженных объектах, для которых выделялась динамическая память. Эта диагностика очень полезна и нацеливает Вас на то, чтобы удалять все объекты — даже те, что обычно сами исчезают при завершении программы. Такая очистка — хороший стиль программирования. После завершения программы просмотрите окно Debug: если Вы встретите там сообщения, включающие слова Memory leaks (утечки памяти) – ищите ошибки.
Пример сообщения об ошибке: Detected memory leaks! Dumping objects -> d:\workdir\temp\test\testview.cpp(53) : {165} normal block at 0x0035C638, 132 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD Object dump complete.
Здесь d:\workdir\temp\test\testview.cpp(53) – имя файла, в котором была выделена память в куче для какого-либо объекта, но не освобождена на момент завершения программы. 53 – номер строки файла, в которой резервировалась память. 132 – размер выделенного участка памяти в байтах. Для перехода к строке программы с ошибкой достаточно сделать двойной щелчок в окне Debug по строке этого сообщения. При желании можно включить нумерацию строк программы путем установки переключателя ToolsèOptionsèSource ControlèText EditorèAll Languages è GeneralèLine Numbers. Каркас приложений MFC Понятие каркаса приложений Одно из определений термина каркас приложений (apllication framework) таково: «интегрированный набор объектно-ориентированных программных компонентов, обеспечивающих все, что нужно для программы общего назначения». Не очень-то полезное определение, не так ли? Если Вы действительно хотите знать, что такое каркас приложений, дочитайте книгу (речь идет о книге Круглински, Уингоу и Шеферда) до конца. Первым Вам поможет пример, с которым Вы познакомитесь чуть позже. |
||||
Последнее изменение этой страницы: 2018-04-12; просмотров: 470. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |