Linguagem de
Programação II
Carlos Oberdan Rolim
Ciência da Computação
Sistemas de Informação
Tratamento de exceções
Tratamento de exceções
Mecanismo que permite tratar de erros em tempo de
execução de modo mais controlado, simplificado e eficiente
que as formas tradicionais de detecção e tratamento de erros
Trata dos mecanismos de disparo, captura e tratamento de
exceções
Problemas durante a execução de um programa
Exceções
Exceções são erros que ocorrem durante a execução de um
programa.
Normalmente, muitos desses erros podem ser previstos pelo
programador que utiliza funções próprias para trata-los
Exceções em C++ constituem um novo mecanismo, uma
ferramenta poderosa e flexível para simplificar a detecção e
tratamento de erros durante a execução do programa
Modo tradicional
Forma tradicional uma função retorna um valor determinando
a ocorrência de um erro.
Necessita verificar o valor retornado todas as vezes
Com o uso de classes e objetos como saber se ocorreu um
erro durante a execução do construtor ou do destrutor ?
O mecanismo de exceções
Exceção em C++ é uma resposta a uma situação anormal
que surge enquanto um programa está em execução
Exemplo: divisão por zero
Podem provocar a transferência do controle para uma parte
do programa para outra parte.
Envolve três conceitos:
Utilização de um bloco try (try)
Captura da uma exceção por um manipulador de exceções (catch)
Disparo de uma exceção (throw)
O mecanismo de exceções
Envolver o bloco suspeito de gerar exceção com um try.
Começa com um comando try seguido do código entre
chaves
Pode ser seguido de um ou mais catch
A captura de uma exceção é feita por um catch. Começa
com a palavra catch seguido seguido por uma declaração de
tipo associada ao tipo de exceção a qual responde
Corpo igual a uma função ou método normal
Será disparado por um throw
Throw indica o disparo de uma exceção quando surge
algum problema implicando o desvio para um outro ponto
(bloco catch)
É seguido de um valor (string, constante, obj, etc) que indica o tipo de
exceção
O mecanismo de exceções
Bloco try
S
Exceção ?
N
Bloco catch
Int main ( ) {
Int dividendo, divisor, quociente;
cin >> dividendo;
cin >> divisor;
try {
if (divisor == 0)
throw “Tentativa de divisão por zero”;
quociente = dividendo / divisor;
cout << “Resultado” << dividendo;
}catch (const char * msg) {
cout << “Erro :” << msg << endl;
}
return 1;
}
Exemplo básico de tratamento de exceção
Informações adicionais
Um try pode por meio de um throw disparar mais de uma
exceção
Disparo de throw lembra um return mas ao invés de retornar
o controle a função chamadora faz com que o programa vá
para o catch correspondente
No bloco catch( const char *msg) existe a correspondencia
com a exceção disparada que é uma string.
Declaração de msg assemelha-se a um argumento de função
Caso um bloco try seja executado sem disparar exceções os
blocos catch não serão executados.
Caso haja o disparo de exceção o bloco catch será
executado e o programa continuará após o último bloco
catch
Int main ( ) {
Int dividendo, divisor, quociente;
cin >> dividendo;
cin >> divisor;
try {
if (divisor == 0)
throw “Tentativa de divisão por zero”;
if (divisor < 0)
throw 8888;
quociente = dividendo / divisor;
cout << “Resultado” << dividendo;
}catch (const char * msg) {
cout << “Erro :” << msg << endl;
}
}catch (int erro) {
cout << “Erro :” << erro << endl;
}
return 1;
}
Exemplo disparando mais de uma exceção
Exceções e funções
A definição de uma função pode ser qualificada com a
especificação da exceção para indicar quais tipos de
exceção essa função pode disparar
E um bloco catch poderá responder a mais de uma exceção
Para qualificar a função usar
nomeFunção (argumentos) throw (excessção1, exceção2,...)
Exemplo
int calcular(int valor1, int valor2) throw (const char *);
Ou
int calcular(int valor1, int valor2) throw (const char *, int);
.....
double calcRaiz(double) throw (const char *);
double calcRaiz(double numero)
throw (const char *){
int main () {
double numero, raizq;
if (numero == 0)
throw “Raiz de num negativo”;
cin >> numero;
return sqrt(numero);
try {
raizq = calcRaiz(numero);
cout << “Raiz:” << raizq;
}
}
catch ( const char * msg) {
cout << “Erro ” << msg << endl;
}
cout << “Termino do programa” << end”;
return 1;
}
Exemplo de código com função qualificada com exceção
Múltiplos blocos try
Pode-se utilizar vários blocos try dentro de um programa
....
cin >> numero;
try {
raizq = calcRaiz(numero);
cout << “Raiz:” << raizq;
} catch ( const char * msg) {
cout << “Erro ” << msg << endl;
}
try {
raizq = Dobro(numero);
cout << “Dobro:” << dobro;
} catch ( const char * msg) {
cout << “Erro ” << msg << endl;
}
Captura de qualquer exceção
É possível usar um bloco catch “genérico” que é executado
quando qualquer exceção for disparada
Basta escrever ... (reticencias) no lugar do tipo de exceção
Int main ( ) {
Int dividendo, divisor, quociente;
cin >> dividendo;
cin >> divisor;
try {
if (divisor == 0)
throw “Tentativa de divisão por zero”;
if (divisor < 0)
throw 8888;
quociente = dividendo / divisor;
cout << “Resultado” << dividendo;
}catch ( ...) {
cout << “Ocorreu uma exceção << endl;
}
return 1;
}
Exemplo com catch genérico capturando qualquer tipo de exceção
Exceções e classes
Exceções podem ser aplicadas em classes com algumas
diferenças
Por exemplo um construtor poderia disparar uma exceção
quando uma chamada ao new fosse mal sucedida
Na utilização de exceções associadas a classes a prática é
disparar objetos como exceções e captura-los com
referência
Para um método que dispara uma exceção, define-se uma
classe de exceção dentro da classe principal para ser
utilizada como o tipo da exceção disparada
Exceções e classes
Declaração de classe dentro da classe é conveniente, pois o
tipo de exceção indica a classe que a originou, além de
ajudar a evitar nomes conflitantes
class vetor {
public:
class erro {
};
private:
....
};
Assim será possível disparar uma exceção do tipo
throw erro();
a ser tratada por um bloco
catch ( vetor :: erro ) { ... }
class numExtenso {
public:
ler();
class Erro {
};
private:
int numero;
};
void numExtenso :: ler () {
cin << numero ;
if (numero <1 || numero > 5)
throw Erro;
}
int main () {
numExtenso num;
try {
num.ler();
}
catch(numExtenso :: Erro ){
cout << “Numero fora do invervalo”;
return 1;
}
return 0;
}
Exemplo com classe de exceção vazia
class numExtenso {
public:
ler();
class Erro {
public:
Erro();
int indice;
};
private:
int numero;
};
int main () {
numExtenso num;
try {
num.ler();
}
void numExtenso :: ler () {
cin << numero ;
if (numero <1 || numero > 5)
throw Erro(numero);
}
numExtenso :: Erro :: Erro (int i){
indice = i;
}
// catch(numExtenso :: Erro ){
catch(numExtenso :: Erro & i ){
cout << i. indice << “ fora do invervalo”;
return 1;
}
return 0;
Exemplo com classe de exceção com membros
}
Exceções e o operador new
Com o mecanismo de exceção quando a alocação de
memória com o operador new for mal sucesidade será
disparada uma exceção do tipo bad_alloc que é uma classe
derivada da classe exception.
Em função da derivação bad_alloc herda um método virtual
chamado what() que retorna um string indicativo da
ocorrência de uma exceção
Essa string varia de acordo com implementação do C++
struct conta {
double saldo[5000];
};
Int main ( ) {
conta * ptr;
try {
cout << “operador new tenta alocar espaco em memória”;
ptr = new conta[10000];
}
catch ( bad_alloc & msg){
cout << String do metodo what(): “<< msg.what() << endl;
return 1;
}
Saída:
delete [ ] ptr;
O operador new tenta alocar espaço em memória
return 0;
}
String do método what(): st9bad_alloc
Exemplo de exceção com alocação dinâmica
Download

try