Programas sempre estão sujeitos a erros. Alguns erros potenciais nós conseguimos identificar e evitar em nosso algoritmo, mas o ideal seria tratar esses erros para caso os esqueçamos em um momento posterior. Nesse sentido o C++ oferece o recurso de tratamento de exceções composto por essas três instruções: try, catch e throw.
Para ilustrar o uso desse recurso, vamos considerar uma situação comum de erros que é a divisão por zero. O algoritmo a seguir ilustra a operação de divisão sujeita a divizão por zero.
#include <iostream>
using namespace std;
float divide(float x, float y) {
return x / y;
}
int main() {
int a, b;
cout << "Digite os valores: ";
cin >> a >> b;
cout << divide(a, b);
return 0;
}
Na função divide() existe a possibilidade do segundo argumento ser zero e gerar um erro na divisão. Então adicicionamos o tratamento de exceção a essa operação. Veja se no bloco try foi adicionado um teste com o segundo valor (o valor do denominador) e verificando se ele é igual a zero. Se ele for igual a zero é lançado, utilizando o comando throw, o erro com o valor “1” (conforme a linha 4 do código abaixo). Esse erro lançado será capturado pelo bloco do catch, sendo o erro lançado recebido no argumento (no caso do exemplo ele está sendo chamado de erro e é um valor inteiro).
float divide(float x, float y) {
try {
if(y == 0) {
throw 1;
} else {
return a/b;
}
} catch(int erro) {
if (erro == 1) {
cout << "Erro de divisao por zero" << endl;
}
}
}
No bloco catch foi testado o valor do erro para mostrar a mensagem apropriada sobre o erro. Nesse caso somente um erro foi identificado, então o teste não precisaria ser feito, deixei apenas para ilustrar a possibilidade. Se várias exceções fossem possíveis, então seria interessante lançá-las com códigos diferentes para mostrar mensagens apropriadas.
Um problema com a função definida é que ela retorna um valor definido apenas caso seja possível fazer a divisão, caso contrário ela retornará qualquer valor. Após o try catch é possível continuar o código sem problemas. No caso do código abaixo foi pedido para retornar zero.
float divide(float x, float y) {
try {
if(y == 0) {
throw 1;
} else {
return x/y;
}
} catch(int erro) {
if (erro == 1) {
cout << "Erro de divisao por zero" << endl;
}
}
return 0;
}
Veja que zero não é realmente uma boa opção de retorno pois zero pode ser um resultado possível de uma divisão (por exemplo zero dividido por 5). Um tratamento melhor nesse caso é mostrado no código a seguir. No código, a função divide() utiliza o throw para lançar o erro para fora da função e esse pode ser capturado na função principal e tratado como foi tratado no código anterior.
#include <iostream>
using namespace std;
float divide(float x, float y) {
if (y == 0) {
throw 1;
} else {
return x/y;
}
}
int main() {
int a, b;
cout << "Digite os valores: ";
cin >> a >> b;
try {
cout << divide(a, b);
} catch(int erro) {
if (erro == 1) {
cout << "Erro de divisao por zero" << endl;
}
}
return 0;
}
Complementando ainda mais o código, supondo que você queria que o usuário informe um valor válido para fazer a operação e, enquanto ele não fornecer um valor valor, continuar solicitando um valor válido. O código abaixo envolve o bloco try catch em um laço de repetição controlado por uma variável chamada error.
int main() {
int a, b;
bool error = false;
cout << "Digite os valores: ";
cin >> a >> b;
do {
try {
cout << divide(a, b);
error = false;
} catch(int erro) {
if (erro == 1) {
cout << "Erro por divisao por zero. Digite outro valor: ";
cin >> b;
}
error = true;
}
} while (error);
return 0;
}
Espero que o tutorial tenha sido útil. Dúvidas, deixe nos comentários.