Tratamento de erros em C++: try/catch e além — guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução ao tratamento de erros em C++

O tratamento de erros é uma das tarefas principais no desenvolvimento de software confiável em C++. Diferente de algumas linguagens (como Python ou Java), onde as exceções são o único mecanismo padrão, C++ oferece ao desenvolvedor várias abordagens. A estabilidade, o desempenho e a legibilidade do código dependem da escolha da estratégia correta. Neste artigo, vamos analisar a construção clássica try/catch, os recursos modernos do padrão C++17/20, bem como métodos alternativos de tratamento de erros.



1. Abordagem clássica: construção try/catch

O mecanismo principal de tratamento de exceções em C++ é baseado em três palavras-chave: try, catch e throw. Uma exceção é um objeto de qualquer tipo que é "lançado" quando ocorre um erro e "capturado" no bloco correspondente.



#include <iostream>#include <stdexcept>

double divide(double a, double b) { if (b == 0) { throw std::runtime_error("Divisão por zero!"); } return a / b;}

int main() { try { double result = divide(10, 0); std::cout << "Resultado: " << result << std::endl; } catch (const std::runtime_error& e) { std::cerr << "Erro: " << e.what() << std::endl; } catch (...) { std::cerr << "Erro desconhecido!" << std::endl; } return 0;}


Pontos importantes:

  • Hierarquia de exceções: é recomendado lançar objetos de classes herdadas de std::exception (por exemplo, std::runtime_error, std::logic_error).
  • Captura por referência: sempre capture exceções por referência constante (const std::exception&), para evitar slicing e cópia desnecessária.
  • Manipulador universal: catch (...) captura qualquer exceção, mas não dá acesso ao objeto de erro. Use-o apenas como último recurso.


2. Abordagens alternativas: códigos de retorno e std::optional

Nem sempre as exceções são a melhor escolha. Em sistemas de alta carga ou programação embarcada, frequentemente preferem-se mecanismos mais leves.



2.1. Códigos de retorno (error codes)

A função retorna um número inteiro ou uma enumeração, indicando sucesso ou o tipo de erro. Este método é simples e eficiente, mas requer verificação explícita do resultado.



enum class ErrorCode { Success, DivisionByZero, Overflow };

ErrorCode safe_divide(double a, double b, double& result) { if (b == 0.0) return ErrorCode::DivisionByZero; result = a / b; return ErrorCode::Success;}

int main() { double res; ErrorCode err = safe_divide(10, 0, res); if (err != ErrorCode::Success) { // Tratamento do erro }}


2.2. std::optional (C++17)

Um contêiner que pode conter um valor ou estar vazio. Ideal para situações onde o erro é a ausência de resultado.



#include <optional>

std::optional<double> divide_opt(double a, double b) { if (b == 0.0) return std::nullopt; return a / b;}

int main() { auto result = divide_opt(10, 2); if (result) { std::cout << *result << std::endl; } else { std::cout << "Erro de divisão" << std::endl; }}


3. Recursos modernos: noexcept e std::expected (C++23)

O padrão C++ continua evoluindo, oferecendo meios cada vez mais expressivos para trabalhar com erros.



3.1. Especificação noexcept

A palavra-chave noexcept indica que a função não lança exceções. Isso ajuda o compilador a otimizar o código e torna a interface mais clara.



void l                

Blogs

Book Recommendations