Condividi tramite


Eccezioni: modifiche alle macro eccezioni nella versione 3.0

Questo è un argomento avanzato.

In MFC versione 3.0 e successive le macro di gestione delle eccezioni sono state modificate per usare le eccezioni C++. Questo articolo descrive in che modo tali modifiche possono influire sul comportamento del codice esistente che usa le macro.

Questo articolo include gli argomenti seguenti:

Tipi di eccezione e macro CATCH

Nelle versioni precedenti di MFC, la macro CATCH usa informazioni sul tipo di runtime MFC per determinare il tipo di un'eccezione. Il tipo dell'eccezione viene determinato, in altre parole, nel sito catch. Con le eccezioni C++, tuttavia, il tipo dell'eccezione viene sempre determinato nel sito throw dal tipo dell'oggetto eccezione generato. Ciò causerà incompatibilità nel raro caso in cui il tipo del puntatore all'oggetto generato differisce dal tipo dell'oggetto generato.

L'esempio seguente illustra la conseguenza di questa differenza tra MFC versione 3.0 e versioni precedenti:

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

Questo codice si comporta in modo diverso nella versione 3.0 perché il controllo passa sempre al primo catch blocco con una dichiarazione di eccezione corrispondente. Risultato dell'espressione throw

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

viene generata come CException*, anche se viene costruita come .CCustomException La macro CATCH nelle versioni MFC 2.5 e precedenti usa CObject::IsKindOf per testare il tipo in fase di esecuzione. Poiché l'espressione

e->IsKindOf(RUNTIME_CLASS(CException));

è true, il primo blocco catch intercetta l'eccezione. Nella versione 3.0, che usa le eccezioni C++ per implementare molte delle macro di gestione delle eccezioni, il secondo blocco catch corrisponde all'eccezione CExceptiongenerata.

Codice simile a questo è insolito. In genere viene visualizzato quando un oggetto eccezione viene passato a un'altra funzione che accetta un generico CException*, esegue l'elaborazione "pre-throw" e infine genera l'eccezione.

Per risolvere questo problema, spostare l'espressione throw dalla funzione al codice chiamante e generare un'eccezione del tipo effettivo noto al compilatore al momento della generazione dell'eccezione.

Generazione nuovamente di eccezioni

Un blocco catch non può generare lo stesso puntatore di eccezione rilevato.

Ad esempio, questo codice è valido nelle versioni precedenti, ma avrà risultati imprevisti con la versione 3.0:

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

L'uso di THROW nel blocco catch determina l'eliminazione del puntatore e , in modo che il sito catch esterno riceva un puntatore non valido. Usare THROW_LAST per generare enuovamente .

Per altre informazioni, vedere Eccezioni: rilevamento ed eliminazione di eccezioni.

Vedi anche

Gestione delle eccezioni