Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это расширенный раздел.
В MFC версии 3.0 и более поздних версиях макросы обработки исключений были изменены на использование исключений C++. В этой статье описывается, как эти изменения могут повлиять на поведение существующего кода, использующего макросы.
В этой статье рассматриваются следующие разделы:
Типы исключений и макрос CATCH
В более ранних версиях MFC макрос CATCH использовал сведения о типе времени выполнения MFC для определения типа исключения; Тип исключения определяется, другими словами, на сайте catch. Однако при исключениях в C++ тип исключения всегда определяется в месте генерации исключения по типу объекта исключения. Это приведет к несовместимости в редких случаях, когда тип указателя на выброшенный объект отличается от типа выброшенного объекта.
В следующем примере показана разница между MFC версии 3.0 и более ранними версиями:
TRY
{
THROW((CException*) new CCustomException());
}
CATCH(CCustomException, e)
{
TRACE("MFC 2.x will land here\n");
}
AND_CATCH(CException, e)
{
TRACE("MFC 3.0 will land here\n");
}
END_CATCH
Этот код ведет себя иначе в версии 3.0, так как управление всегда передается в первый catch
блок, для которого существует соответствующее объявление исключения. Результат выражения броска
THROW((CException*) new CCustomException());
выбрасывается как CException*
, хотя он создается как CCustomException
. Макрос CATCH в MFC версии 2.5 и более ранних используется CObject::IsKindOf
для тестирования типа во время выполнения. Так как выражение
e->IsKindOf(RUNTIME_CLASS(CException));
если истинно, первый блок catch перехватывает исключение. В версии 3.0, которая использует исключения C++ для реализации многих макросов обработки исключений, второй блок catch соответствует выброшенному CException
.
Код, подобный этому, является редким. Обычно возникает, когда объект исключения передается другой функции, которая принимает его как универсальный CException*
, выполняет обработку перед выбрасыванием и, наконец, выбрасывает исключение.
Чтобы обойти эту проблему, переместите выражение броска из функции в вызывающий код и создайте исключение фактического типа, известного компилятору во время создания исключения.
Re-Throwing Исключения
Блок catch не может выбросить тот же указатель исключения, который он поймал.
Например, этот код действителен в предыдущих версиях, но будет иметь непредвиденные результаты с версией 3.0:
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e)
{
THROW(e); // Wrong. Use THROW_LAST() instead
}
END_CATCH
}
Использование THROW в блоке catch приводит к удалению указателя e
, из-за чего внешнее место catch получит недопустимый указатель. Используйте THROW_LAST для повторного выбрасывания e
.
Дополнительные сведения см. в разделе "Исключения: перехват и удаление исключений".