Exceções: Alterações exceção Macros na versão 3.0
Este é um tópico avançado.
MFC versão 3.0 e posterior, as macros de manipulação de exceções foram alteradas para usar exceções do C++.Esse artigo informa como essas alterações podem afetar o comportamento do código existente que usa as macros.
Este artigo aborda os seguintes tópicos:
Tipos de exceção e a macro CATCH
Relançar exceções
Tipos de exceção e a macro CATCH
Em versões anteriores do MFC, o CATCH macro usada informações sobre o tipo de time de execução MFC para determinar o tipo da exceção; tipo da exceção é determinado, em outras palavras, no site catch.Com as exceções do C++, no entanto, tipo da exceção é sempre determinado no site throw pelo tipo do objeto de exceção é acionada.Isso fará com que incompatibilidades no caso raro onde o tipo de ponteiro para o objeto gerado difere do tipo de objeto gerado.
O exemplo a seguir ilustra a conseqüência essa diferença entre MFC versão 3.0 e versões 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
Se esse código comporta de forma diferente na versão 3.0 porque sempre passa o controle para o primeiro catch bloco com uma declaração de exceção correspondente.O resultado da expressão throw
THROW( (CException*) new CCustomException() );
é lançada sistema autônomo um CException *, mesmo que ela é construída sistema autônomo um CCustomException.The CATCH macro em MFC versões 2.5 e anteriores usa CObject::IsKindOf Para testar o tipo em time de execução. Porque a expressão
e->IsKindOf(RUNTIME_CLASS(CException));
é verdade, o primeiro bloco catch captura a exceção.Na versão 3.0, que usa as exceções do C++ para implementar várias das macros manipulação de exceção, o segundo capturar correspondências de bloco a geradas CException.
Código como este é incomum.Geralmente aparece quando um objeto de exceção é passado para outra função que aceita um genérico CException *, executa o processamento "pre-throw" e finalmente lança a exceção.
Para contornar esse problema, mova a expressão throw da função para o código de chamada e lançar uma exceção do tipo real conhecido para o compilador no time a exceção é gerada.
Re-Throwing exceções
Um bloco catch não pode lançar o ponteiro de exceção mesmo que ele detectado.
Por exemplo, esse código era válido nas versões anteriores, mas terá resultados inesperados com versão 3.0:
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH( CException, e )
{
THROW( e ); // Wrong. Use THROW_LAST() instead
}
END_CATCH
}
Usando THROW no bloco catch faz com que o ponteiro e a ser excluído, para que o site externo catch irá receber um ponteiro inválido. Use THROW_LAST para relançar e.
Para obter mais informações, consulte Exceções: Captura e excluindo exceções.