Excepciones: Cambios en las macros de excepción en la versión 3.0
Éste es un tema avanzado.
En la versión 3.0 de MFC y versiones posteriores, las macros de control de excepciones se han cambiado para utilizar excepciones de C++. Este artículo indica cómo esos cambios pueden afectar al comportamiento del código existente que utiliza las macros.
En este artículo se tratan los siguientes temas:
Tipos de excepción y la macro de CATCH
Excepciones Re- que producen
Tipos de excepción y la macro de CATCH
En versiones anteriores de MFC, la información de tipo utilizada macro en tiempo de ejecución de CATCH MFC para determinar el tipo de excepción; determinan el tipo de excepción, es decir en el bloque catch. Con las excepciones de C++, sin embargo, el tipo del objeto de excepción determina el tipo de excepción siempre en el sitio de captura que se produce. Esto producirá incompatibilidades en el caso poco frecuente donde el tipo de puntero al objeto iniciado difiere del tipo de objeto iniciado.
El ejemplo siguiente se muestra el resultado de esta diferencia entre la versión 3.0 de MFC y versiones anteriores:
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
Este código se comporta de manera diferente en la versión 3.0 porque el control pasa siempre en primer catch bloqueado con una excepción- declaración coincidente. El resultado de la expresión throw
THROW( (CException*) new CCustomException() );
se produce como CException*, aunque se genera como CCustomException. La macro de CATCH en las versiones 2.5 de MFC y anterior utiliza CObject::IsKindOf para probar el tipo en tiempo de ejecución. Dado que la expresión
e->IsKindOf(RUNTIME_CLASS(CException));
es true, las primeras capturas del bloque catch la excepción. En la versión 3.0, que utiliza las excepciones de C++ para implementar muchas de las macros de control de excepciones, el segundo bloque catch coincide con CExceptionsystem.typeloadexception.
El código siguiente es infrecuente. Se produce normalmente cuando un objeto de excepción se pasa a otra función que acepta **CException***genérico, realiza el procesamiento de “pre- throw” y, finalmente produce una excepción.
Para evitar este problema, mover la expresión throw de la función al código de llamada y producir una excepción de tipo real conocido al compilador cuando se genera una excepción.
Excepciones Re- que producen
Un bloque catch no puede producir el mismo puntero de la excepción que cogió.
Por ejemplo, este código era válido en las versiones anteriores, pero tendrá resultados inesperados con la versión 3.0:
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH( CException, e )
{
THROW( e ); // Wrong. Use THROW_LAST() instead
}
END_CATCH
}
Mediante THROW en el bloque catch hace que el puntero e que se va a eliminar, de modo que el sitio externo de captura recibe un puntero no válido. Uso THROW_LAST al re- captura e.
Para obtener más información, vea Excepciones: Detectando y eliminar Excepciones.