Udostępnij za pośrednictwem


Wyjątki: zmiany w makrach 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 przechwytywania. Jednak w przypadku wyjątków języka C++ typ wyjątku jest zawsze określany w lokacji zgłaszanej przez typ zgłoszonego obiektu wyjątku. Spowoduje to niezgodności w rzadkich przypadkach, w których typ wskaźnika do obiektu rzuconego różni się od typu zgłaszanego 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());

element jest zgłaszany jako element CException*, mimo że jest on 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++, aby zaimplementować wiele makr obsługi wyjątków, drugi blok catch jest zgodny z zgłoszonym CException.

Kod podobny do tego jest nietypowy. Zwykle pojawia się, gdy obiekt wyjątku jest przekazywany do innej funkcji, która akceptuje ogólny CException*, wykonuje przetwarzanie "przedrzucanie", 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.

Ponowne zgłaszanie wyjątków

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 funkcji THROW w bloku catch powoduje usunięcie wskaźnika e , dzięki czemu zewnętrzna lokacja przechwytywania otrzyma nieprawidłowy wskaźnik. Użyj THROW_LAST , aby ponownie zgłosić element e.

Aby uzyskać więcej informacji, zobacz Wyjątki: przechwytywanie i usuwanie wyjątków.

Zobacz też

Obsługa wyjątków