Udostępnij przez


Wyjątki: zmiany makr wyjątków w wersji 3.0

Jest to zaawansowany temat.

W MFC w wersji 3.0 lub nowszej makra obsługi wyjątków zostały zmienione w celu używania wyjątków języka C++. W tym artykule opisano, jak te zmiany mogą mieć wpływ na zachowanie istniejącego kodu korzystającego z makr.

W tym artykule opisano następujące tematy:

Typy wyjątków i makro CATCH

We wcześniejszych wersjach MFC makro CATCH używało informacji o typie czasu wykonywania MFC w celu określenia typu wyjątku; typ wyjątku jest określany, innymi słowy, w miejscu połowu. Jednak w przypadku wyjątków w języku C++ typ wyjątku jest zawsze określany w miejscu, gdzie obiekt wyjątku jest zgłaszany, na podstawie jego typu. Spowoduje to niezgodności w rzadkich przypadkach, gdy typ wskaźnika do rzucanego obiektu różni się od typu tego obiektu.

Poniższy przykład ilustruje konsekwencję tej różnicy między MFC w wersji 3.0 i starszych wersji:

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

Ten kod działa inaczej w wersji 3.0, ponieważ kontrolka zawsze przechodzi do pierwszego catch bloku z zgodną deklaracją wyjątku. Wynik wyrażenia 'throw'

THROW((CException*) new CCustomException());

jest wyrzucany jako CException*, mimo że jest skonstruowany jako CCustomException. Makro CATCH w MFC w wersji 2.5 i starszych używa CObject::IsKindOf do testowania typu w czasie wykonywania. Ponieważ wyrażenie

e->IsKindOf(RUNTIME_CLASS(CException));

to prawda, pierwszy blok catch przechwytuje wyjątek. W wersji 3.0, która używa wyjątków języka C++ do implementacji wielu makr obsługi wyjątków, drugi blok catch odpowiada zgłaszanemu CException.

Kod podobny do tego jest nietypowy. Zwykle pojawia się, gdy obiekt wyjątku jest przekazywany do innej funkcji, która akceptuje ogólny typ CException*, wykonuje przetwarzanie przed wyrzuceniem, a na koniec zgłasza wyjątek.

Aby obejść ten problem, przenieś wyrażenie throw z funkcji do kodu wywołującego i zgłoś wyjątek rzeczywistego typu znanego kompilatorowi w momencie wygenerowania wyjątku.

wyjątki Re-Throwing

Blok catch nie może zgłosić tego samego wskaźnika wyjątku, który został przechwycony.

Na przykład ten kod był prawidłowy w poprzednich wersjach, ale będzie miał nieoczekiwane wyniki z wersją 3.0:

TRY
{
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)
{
   THROW(e);    // Wrong. Use THROW_LAST() instead
}
END_CATCH
   }

Użycie THROW w bloku catch powoduje usunięcie wskaźnika e, co powoduje, że zewnętrzne miejsce przechwytywania otrzyma nieprawidłowy wskaźnik. Użyj THROW_LAST, aby ponownie rzucić e.

Więcej informacji znajdziesz w Wyjątki: przechwytywanie i usuwanie wyjątków.

Zobacz także

Obsługa wyjątków