Compartir a través de


Excepciones: cambios en macros de excepción en la versión 3.0

Se trata de un tema avanzado.

En MFC versión 3.0 y posteriores, se han cambiado las macros de control de excepciones para usar excepciones de C++. En este artículo se indica cómo esos cambios pueden afectar al comportamiento del código existente que usa las macros.

En este artículo se tratan los temas siguientes:

Tipos de excepciones y la macro CATCH

En versiones anteriores de MFC, la macro CATCH usaba información de tipo de tiempo de ejecución de MFC para determinar el tipo de una excepción; El tipo de excepción se determina, en otras palabras, en el sitio de captura. Sin embargo, con excepciones de C++, el tipo de excepción siempre se determina en el sitio iniciado por el tipo del objeto de excepción que se produce. Esto provocará incompatibilidades en el caso poco frecuente en el que el tipo del puntero al objeto producido difiere del tipo del objeto producido.

En el ejemplo siguiente se muestra la consecuencia de esta diferencia entre MFC versión 3.0 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 forma diferente en la versión 3.0 porque el control siempre pasa al primer catch bloque con una declaración de excepción coincidente. Resultado de la expresión throw

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

se produce como , CException*aunque se construye como .CCustomException La macro CATCH de las versiones 2.5 y anteriores de MFC usa CObject::IsKindOf para probar el tipo en tiempo de ejecución. Dado que la expresión

e->IsKindOf(RUNTIME_CLASS(CException));

es true, el primer bloque catch detecta la excepción. En la versión 3.0, que usa excepciones de C++ para implementar muchas de las macros de control de excepciones, el segundo bloque catch coincide con el producido CException.

El código como este es poco común. Normalmente aparece cuando se pasa un objeto de excepción a otra función que acepta un genérico CException*, realiza el procesamiento "previo" y, por último, produce la excepción.

Para solucionar este problema, mueva la expresión throw de la función al código de llamada y genere una excepción del tipo real conocido para el compilador en el momento en que se genera la excepción.

excepciones de Re-Throwing

Un bloque catch no puede producir el mismo puntero de excepción que detectó.

Por ejemplo, este código era válido en 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
   }

El uso de THROW en el bloque catch hace que el puntero e se elimine, de modo que el sitio catch externo reciba un puntero no válido. Use THROW_LAST para volver a iniciar e.

Para obtener más información, vea Excepciones: Detectar y eliminar excepciones.

Consulte también

Manejo de Excepciones