Partilhar via


Exceções: Alterações de Macros de exceção na versão 3.0

Este é um tópico avançado.

No MFC versão 3.0 e posterior, as macros de manipulação de exceção 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 de tipo de tempo 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 que é lançado.Isso pode causar incompatibilidades no caso raro onde o tipo de ponteiro para o objeto lançado difere do tipo de objeto gerado.

O exemplo a seguir ilustra a conseqüência dessa 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

Esse código vária 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 como um CException *, mesmo que ela é construída como um CCustomException.O CATCH macro no MFC versões 2.5 e anterior usa CObject::IsKindOf para testar o tipo em tempo 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 macros de manipulação de exceção, o segundo bloco catch corresponde a lançada 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 de "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 do compilador no momento em que a exceção é gerada.

Relançar exceções

Um bloco catch não pode lançar o mesmo ponteiro de exceção detectado por ele.

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 Lançar na catch bloco faz com que o ponteiro e a ser excluído, para que o site catch externa receberá um ponteiro inválido.Use THROW_LAST to re-throw e.

Para obter mais informações, consulte exceções: detectar e excluir exceções.

Consulte também

Conceitos

Tratamento de exceção no MFC