Condividi tramite


Eccezioni: modifiche alle macro eccezioni nella versione 3.0

Si tratta di un argomento avanzato.

Nelle versioni di MFC 3,0 e versioni successive, le macro di gestione delle eccezioni sono state modificate per utilizzare le eccezioni C++. Questo articolo descrive come tali modifiche possono influire sul comportamento del codice esistente che utilizza le macro.

Questo articolo tratta i seguenti argomenti:

  • Tipi di eccezione e la macro CATCH

  • Ri-generazione di eccezioni

Tipi di eccezione e la macro CATCH

Nelle versioni precedenti di MFC, la macro CATCH utilizza le informazioni sui tipi di runtime MFC per determinare il tipo di eccezioni; il tipo di eccezioni è determinato, ovvero al sito catch. Con le eccezioni C++, tuttavia, il tipo di eccezione sono sempre determinate al sito throw dal tipo dell'oggetto dell'eccezione generato. Ciò causerà incompatibilità nei rari casi in cui il tipo del puntatore all'oggetto generato è diverso dal tipo dell'oggetto generato.

Nell'esempio seguente viene illustrato il risultato di questa differenza tra la versione di MFC 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 prima a Catch il blocco con una dichiarazione dell'eccezione corrispondente. Risultato dell'espressione lanciata

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

viene generato come CException*, anche se viene costruito come CCustomException. La macro CATCH in MFC versione 2.5 e precedente usa CObject::IsKindOf per verificare il tipo in fase di esecuzione. A causa dell'espressione

e->IsKindOf(RUNTIME_CLASS(CException));

è true, i primi blocchi catch catturano l'eccezione. Nella versione 3,0, che utilizza le eccezioni C++ per implementare molte delle macro di gestione delle eccezioni, il secondo blocco catch corrisponde l'eccezione CException.

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

Per risolvere questo problema, spostare l'espressione throw dalla funzione nel codice chiamante e genera un'eccezione di tipo conosciuto dal compilatore quando viene generata un'eccezione.

Ri-generazione di eccezioni

Un blocco catch non può generare lo stesso puntatore di eccezione che ha intercettato.

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
}

Utilizzando THROW nel blocco catch causa l'eliminazione del puntatore e in modo che il sito esterno catch riceverà un puntatore non valido. Utilizzare THROW_LAST per generare nuovamente e.

Per ulteriori informazioni, consultare Eccezioni: Rilevazione e l'eliminazione delle eccezioni.

Vedere anche

Concetti

Gestione delle eccezioni in MFC