C++: Tratamento de Exceções
Última atualização: 2026-08-26
Quando os programas executam, coisas inesperadas sempre acontecem: arquivos não existem, a memória acaba, a rede se desconecta...
Se não forem tratados, o programa falha.
O tratamento de exceções é o "airbag" do programa — quando ocorrem problemas, ele responde de forma graciosa em vez de falhar abruptamente.
1. Noções Básicas de Tratamento de Exceções
(1) 1.1 O que é uma Exceção?
Uma exceção é um erro ou condição inesperada que ocorre durante a execução do programa.
Exceções Comuns:
- Divisão por zero
- Acesso a ponteiro nulo
- Falha ao abrir arquivo
- Falha na alocação de memória
(2) 1.2 Os Três Elementos do Tratamento de Exceções
O tratamento de exceções do C++ usa três palavras-chave:
| Palavra-chave | Função |
|---|---|
try |
Monitorar código que pode lançar erros |
catch |
Capturar e tratar exceções |
throw |
Lançar uma exceção |
(3) 1.3 Exemplo Básico
Exemplo: Exceção de Divisão por Zero (Dificuldade ⭐)
▶ Exemplo 1: Exemplo de Código (Dificuldade ⭐)
#include <iostream>
int divide(int a, int b) {
if (b == 0) {
throw "Divisor cannot be 0!"; // Throw exception
}
return a / b;
}
int main() {
try {
std::cout << divide(10, 2) << std::endl; // Normal
std::cout << divide(10, 0) << std::endl; // Throws exception
}
catch (const char* msg) { // Catch exception
std::cerr << "Error: " << msg << std::endl;
}
std::cout << "Program continues running" << std::endl;
return 0;
}
Saída:
5
Error: Divisor cannot be 0!
Program continues running
Resultado da Execução:
5
Error: Divisor cannot be 0!
Program continues running
💡 Dica:
- Após uma exceção ser capturada, o programa não falha — ele continua executando
2. Tipos de Exceção
(1) 2.1 Tipos que Podem Ser Lançados
throw pode lançar qualquer tipo:
| Tipo | Exemplo |
|---|---|
| Tipos básicos | throw 42; |
| Strings | throw "error"; |
| Exceções padrão | throw std::runtime_error("error"); |
| Exceções personalizadas | throw MyException(); |
(2) 2.2 Capturando Múltiplas Exceções
Exemplo: Capturando Diferentes Tipos de Exceções (Dificuldade ⭐⭐)
#include <iostream>
### ▶ Exemplo 2: Exemplo de Código (Dificuldade ⭐)
#include <string>
void process(int value) {
if (value == 0) {
throw 0; // Throw int
}
if (value < 0) {
throw std::string("Negative number"); // Throw string
}
}
int main() {
try {
process(-5);
}
catch (int e) {
std::cerr << "Caught int exception: " << e << std::endl;
}
catch (const std::string& e) {
std::cerr << "Caught string exception: " << e << std::endl;
}
return 0;
}
3. Exceções Padrão
(1) 3.1 Hierarquia std::exception
A biblioteca padrão do C++ define um conjunto de classes de exceção, todas em stdexcept:
std::exception
├── std::logic_error
│ ├── std::invalid_argument
│ ├── std::out_of_range
│ └── std::length_error
└── std::runtime_error
├── std::overflow_error
└── std::underflow_error
(2) 3.2 Exceções Padrão Comuns
| Classe de Exceção | Descrição |
|---|---|
std::invalid_argument |
Argumento inválido |
std::out_of_range |
Fora dos limites |
std::runtime_error |
Erro em tempo de execução |
std::bad_alloc |
Falha na alocação de memória (new falhou) |
Exemplo: Usando Exceções Padrão (Dificuldade ⭐⭐)
#include <iostream>
#include <stdexcept>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3};
try {
v.at(10); // Out-of-bounds access
}
catch (const std::out_of_range& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
4. Exceções Personalizadas
(1) 4.1 Herdando de std::exception
Melhor Prática: Classes de exceção personalizadas devem herdar de std::exception.
Exemplo: Classe de Exceção Personalizada (Dificuldade ⭐⭐⭐)
#include <iostream>
#include <exception>
#include <string>
// Custom exception class
class MyException : public std::exception {
private:
std::string msg;
public:
MyException(const std::string& msg) : msg(msg) {}
const char* what() const noexcept override {
return msg.c_str();
}
};
int main() {
try {
throw MyException("Custom exception");
}
catch (const MyException& e) {
std::cerr << "Caught custom exception: " << e.what() << std::endl;
}
return 0;
}
5. Segurança de Exceções
(1) 5.1 O que é Segurança de Exceções?
Segurança de exceções significa que mesmo quando uma exceção é lançada, o programa mantém um estado consistente (sem vazamento de recursos, sem corrupção de dados).
Três níveis de garantia:
- Garantia básica: O estado do programa é consistente, mas pode ter mudado
- Garantia forte: A operação ou tem sucesso ou é completamente revertida (como se nunca tivesse acontecido)
- Garantia de não-lançamento: A função nunca lança uma exceção
(2) 5.2 RAII — Uma Ferramenta Poderosa para Gerenciamento de Recursos
RAII (Resource Acquisition Is Initialization): Gerenciar recursos através de objetos, com destrutores liberando-os automaticamente.
Exemplo: Usando Smart Pointers para Segurança de Exceções (Dificuldade ⭐⭐⭐)
#include <iostream>
#include <memory>
void process() {
// Use unique_ptr to manage memory; even if an exception is thrown, it will be automatically freed
std::unique_ptr<int> p(new int(42));
// ... code that may throw exceptions ...
std::cout << *p << std::endl;
} // p is automatically freed
int main() {
try {
process();
}
catch (...) {
std::cerr << "Caught exception" << std::endl;
}
return 0;
}
6. A Palavra-chave noexcept
(1) 6.1 Uso Básico
O C++11 introduziu noexcept, que declara que uma função não lança exceções.
Exemplo: Declarando Não-Lançamento (Dificuldade ⭐)
void safeFunction() noexcept {
// This function guarantees not to throw exceptions
}
void unsafeFunction() {
// May throw exceptions
}
💡 Dica:
- Destrutores são
noexceptpor padrão noexceptajuda o compilador a otimizar
❓ Perguntas Frequentes
P: Quando devo usar exceções? R: Para situações verdadeiramente inesperadas, não para fluxo de controle normal.
P: O que é catch(...)? R: Captura todas as exceções, tipicamente usado para limpar recursos antes de relançar.
try {
// ...
}
catch (...) {
// Clean up resources
throw; // Re-throw
}
P: Construtores podem lançar exceções? R: Sim, mas tenha cuidado com vazamentos de memória. Use smart pointers ou RAII para gerenciar recursos.
▶ Exemplo 3: Capturando Exceções (Dificuldade ⭐)
#include <iostream>
#include <stdexcept>
double divide(double a, double b) {
if (b == 0) {
throw std::runtime_error("Divisor cannot be 0");
}
return a / b;
}
int main() {
try {
std::cout << divide(10, 2) << std::endl;
std::cout << divide(10, 0) << std::endl;
} catch (const std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
}
return 0;
}
Saída:
Error: Divisor cannot be 0
try-catch captura exceções, throw lança exceções. what() retorna a mensagem de erro.
| Conceito | Ponto-chave |
|---|---|
| try-catch-throw | Os três elementos do tratamento de exceções |
| Exceções padrão | std::runtime_error, etc. |
| Exceções personalizadas | Herdar de std::exception |
| Segurança de exceções | RAII garante sem vazamento de recursos |
| noexcept | Declara que uma função não lança exceções |
📖 Resumo
- try/catch: Capturar e tratar exceções
- throw: Lançar exceções
- std::exception: Classe base de exceção padrão
- Exceções personalizadas: Implemente suas próprias classes de exceção herdando de
std::exception
📝 Exercícios
-
Básico (Dificuldade ⭐): Escreva uma função de divisão que lança
std::runtime_errorquando o divisor é 0, e usetry/catchemmainpara capturar e exibir a mensagem de erro. -
Intermediário (Dificuldade ⭐⭐): Defina uma classe de exceção personalizada (herdando de
std::exception) com dois campos: código de erro e descrição do erro. Após lançá-la, recupere ambos no bloco catch. -
Desafio (Dificuldade ⭐⭐⭐): Implemente uma classe "guarda de recursos" que adquire recursos no construtor e os libera no destrutor. Mesmo que uma exceção seja lançada entre eles, os recursos são corretamente liberados (princípio RAII).
- Três partes do tratamento de exceções: try monitora, throw lança, catch captura
- Classes de exceção padrão herdam de std::exception
- catch corresponde por tipo; múltiplos blocos catch são verificados de cima para baixo
- Desenrolamento de pilha: após uma exceção ser lançada, catch é buscado camada por camada
- noexcept declara que uma função não lança exceções
Próxima Lição: Operações Avançadas com Arquivos (#41)