Respostas:
std::exception
é a classe cujo único objetivo é servir como classe base na hierarquia de exceções. Não tem outros usos. Em outras palavras, conceitualmente é um classe abstrata (mesmo que não seja definida como classe abstrata no significado C ++ do termo).
std::runtime_error
é uma classe mais especializada, descendente de std::exception
, destinada a ser lançada em caso de vários erros de tempo de execução . Tem um duplo objetivo. Ele pode ser lançado sozinho ou pode servir como uma classe base para vários tipos ainda mais especializados de exceções de erro de tempo de execução, como std::range_error
, std::overflow_error
etc. Você pode definir suas próprias classes de exceção descendentes destd::runtime_error
e também sua própria exceção classes descendentes de std::exception
.
Assim como std::runtime_error
, a biblioteca padrão contém std::logic_error
, também descendentes std::exception
.
O objetivo de ter essa hierarquia é dar ao usuário a oportunidade de usar todo o poder do mecanismo de manipulação de exceção do C ++. Como a cláusula 'catch' pode capturar exceções polimórficas, o usuário pode escrever cláusulas 'catch' que podem capturar tipos de exceção de uma subárvore específica da hierarquia de exceções. Por exemplo, catch (std::runtime_error& e)
captará todas as exceções da std::runtime_error
subárvore, permitindo que todas as outras passem (e voem ainda mais na pilha de chamadas).
PS Projetar uma hierarquia útil de classes de exceção (que permitiria capturar apenas os tipos de exceção nos quais você está interessado em cada ponto do seu código) é uma tarefa não trivial. O que você vê na biblioteca C ++ padrão é uma abordagem possível, oferecida a você pelos autores da linguagem. Como você vê, eles decidiram dividir todos os tipos de exceção em "erros de tempo de execução" e "erros lógicos" e permitem prosseguir a partir daí com seus próprios tipos de exceção. É claro que existem maneiras alternativas de estruturar essa hierarquia, que podem ser mais apropriadas em seu design.
Atualização: Portabilidade Linux vs Windows
Como Loki Astari e unixman83 observaram em suas respostas e comentários abaixo, o construtor da exception
classe não aceita argumentos de acordo com o padrão C ++. O Microsoft C ++ possui um construtor que aceita argumentos na exception
classe, mas isso não é padrão. A runtime_error
classe tem um construtor recebendo argumentos (char*
) nas duas plataformas, Windows e Linux. Para ser portátil, use melhor runtime_error
.
(E lembre-se, apenas porque uma especificação do seu projeto diz que seu código não precisa ser executado no Linux, isso não significa que ele nunca precisa ser executado no Linux.)
std::exception
. Claro, todas as std
coisas lançam classes derivadas disso, mas não há absolutamente nenhuma razão para lançar apenas std::exception
objetos derivados.
std::exception
deve ser considerada (observe o considerado) a base abstrata da hierarquia de exceções padrão. Isso ocorre porque não há mecanismo para transmitir uma mensagem específica (para fazer isso, você deve derivar e se especializar what()
). Não há nada que o impeça de usar std :: exception e, para aplicativos simples, pode ser tudo o que você precisa.
std::runtime_error
por outro lado, possui construtores válidos que aceitam uma string como uma mensagem. Quando what()
é chamado um ponteiro const char, é retornado que aponta para uma string C que possui a mesma string que foi passada para o construtor.
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
std::exception(std::string)
. Agora percebo que devo jogar std::runtime_error
se quiser que meu código funcione no Linux (GCC).