Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Toto je rozšířené téma.
V prostředí MFC verze 3.0 a novější byly makra zpracování výjimek změněna tak, aby používala výjimky jazyka C++. Tento článek popisuje, jak tyto změny můžou ovlivnit chování existujícího kódu, který používá makra.
Tento článek se zabývá následujícími tématy:
Typy výjimek a makro CATCH
V dřívějších verzích prostředí MFC makro CATCH používalo informace o typu běhového prostředí MFC k určení typu výjimky; typ výjimky je určen jinými slovy v lokalitě catch. Při výjimkách jazyka C++ je však typ výjimky vždy určen v lokalitě vyvolání typem objektu výjimky, který je vyvolán. To způsobí nekompatibilitu ve výjimečných případech, kdy se typ ukazatele na vyvolaný objekt liší od typu vyvolaného objektu.
Následující příklad ukazuje výsledek tohoto rozdílu mezi mfc verze 3.0 a dřívějšími verzemi:
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
Tento kód se ve verzi 3.0 chová odlišně, protože ovládací prvek se vždy předává do prvního catch bloku s odpovídající deklarací výjimky. Výsledek výrazu throw
THROW((CException*) new CCustomException());
je vyvolán jako CException*, i když je vytvořen jako CCustomException. Makro CATCH v prostředí MFC verze 2.5 a starší používá CObject::IsKindOf k otestování typu za běhu. Vzhledem k tomu, že výraz
e->IsKindOf(RUNTIME_CLASS(CException));
Pokud je pravda, první blok zachytí výjimku. Ve verzi 3.0, která používá výjimky jazyka C++ k implementaci mnoha maker zpracování výjimek, druhý blok catch odpovídá vyvolanému CException.
Kód podobný tomuto je neobvyklý. Obvykle se zobrazí, když je objekt výjimky předán jiné funkci, která přijímá obecný CException*, provádí zpracování "před vyvolání" a nakonec vyvolá výjimku.
Chcete-li tento problém obejít, přesuňte výraz throw z funkce do volajícího kódu a vyvolejte výjimku skutečného typu známého kompilátoru při generování výjimky.
Výjimky Re-Throwing
Blok catch nemůže vyvolat stejný ukazatel výjimky, který již zachytil.
Tento kód byl například platný v předchozích verzích, ale bude mít neočekávané výsledky s verzí 3.0:
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e)
{
THROW(e); // Wrong. Use THROW_LAST() instead
}
END_CATCH
}
Použití THROW v bloku catch způsobí smazání ukazatele e, takže vnější místo zachycení dostane neplatný ukazatel. K opětovnému vyvolání použijte e .
Další informace naleznete v tématu Výjimky: Zachytávání a odstraňování výjimek.