Eccezioni: Modifiche alle macro di eccezione 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++.In questo articolo descritto come tali modifiche possono influire sul comportamento del codice esistente che utilizza le macro.
Questo articolo vengono trattati i seguenti argomenti:
Tipi di eccezione e la macro di FERMO
Ri-generare le eccezioni
Tipi di eccezione e la macro di FERMO
Nelle versioni precedenti di MFC, la macro di CATCH utilizza le informazioni sul tipo 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 eccezioni è sempre determinato il sito di generazione dal tipo di eccezione generato.In questo modo le incompatibilità nei rari casi in cui il tipo del puntatore all'oggetto generato è diverso da quello 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 al primo blocco catch con una dichiarazione dell'eccezione corrispondente.Il risultato dell'espressione throw
THROW( (CException*) new CCustomException() );
viene generato come CException*, anche se viene costruito quale CCustomException.La macro di CATCH in MFC versione 2,5 e utilizzi più a breve termine CObject::IsKindOf verificare il tipo in fase di esecuzione.Poiché l'espressione
e->IsKindOf(RUNTIME_CLASS(CException));
è true, i primi intercetti di blocco catch 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 CExceptiongenerato.
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 di “pre-tiro„ e infine genera l'eccezione.
Per ovviare a questo problema, spostare l'espressione throw dalla funzione nel codice chiamante e generare un'eccezione di tipo effettivo noto al compilatore quando viene generata l'eccezione.
Ri-Generare le eccezioni
Un blocco catch non è possibile generare lo stesso puntatore di eccezione che ha intercettato.
Ad esempio, questo codice è valido nelle versioni precedenti, ma sarà 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 fa sì che il puntatore e l'eliminazione, in modo che il sito esterno catch riceverà un puntatore non valido.Utilizzo THROW_LAST a eccezione e.
Per ulteriori informazioni, vedere eccezioni: Rilevazione e l'eliminazione delle eccezioni.