Sdílet prostřednictvím


Výjimky: Změny maker pro výjimky ve verzi 3.0

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ěhu 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));

je pravda, první blok zachycení výjimku zachytí. 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 vyvoláte výjimku skutečného typu známého kompilátoru v době generování výjimky.

Opětovné vyvolání výjimek

Blok catch nemůže vyvolat stejný ukazatel výjimky, který 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í funkce THROW v bloku catch způsobí odstranění ukazatele e , aby vnější web zachycení obdržel neplatný ukazatel. K opětovnému vyvolání epoužijte THROW_LAST .

Další informace naleznete v tématu Výjimky: Zachytávání a odstraňování výjimek.

Viz také

Zpracování výjimek