Sete, tratamento de exceção

  • Mecanismo de tratamento de exceções (mecanismo de tratamento de exceções): Como designers, não sabemos o quão prejudicial um possível problema é para todo o programa, apenas o usuário desta função conhece a gravidade do problema. Portanto, nossa responsabilidade é notificar o usuário e dizer-lhe o que aconteceu.O mecanismo de tratamento de exceções é usado para concluir a tarefa de notificação.
  • O mecanismo de tratamento de exceção inclui: identificação de exceção e método de tratamento de problema + exceção.
  • Depois que a exceção ocorre, a execução do programa normal é suspensa e o mecanismo de tratamento de exceções começa a pesquisar locais no programa que são capazes de tratar a exceção. Depois que a exceção for processada, a execução do programa continuará (retomará) e continuará a partir do ponto de tratamento da exceção .
  • Exceções de lançamento (lançadas): as throwexpressões parecem chamadas de função, as exceções são algum tipo de objeto, na maioria das vezes pertencem a uma classe de exceção específica (pode formar um sistema de herança).
inline void Triangular_iterator::
check_integrity()
{
    
    
	if(_index >= Triangular::_max_elems)
		throw iterator_overflow(_index, Triangular::_max_elems);
		
		if(_index > Triangular::_elems.size())
			Triangular::gen_elements(_index + 1);
}

//iterator_overflow类的定义
class iterator_overflow{
    
    
public:
	iterator_overflow(int index, int max)
		: _index(index), _max(max) {
    
    }
	int index() {
    
    return _index;}
	int max() 	{
    
    return _max;}
	
	void what_happened(ostream &os = cerr) {
    
    
		os << "Internal error: current index "
		   << _index << " exceeds maximum bound: "
		   << _max;	
	}
	
private:
	int _index;
	int _max;
};
  • A throwexpressão acima irá chamar diretamente o construtor com dois parâmetros. Você também pode especificar o nome do objeto lançado:
if(_index > Triangular::_max_elems)
{
    
    
	iterator_overflow ex(_index, Triangular::_max_elems);
	throw ex;
}
  • Exceções de captura: use uma única cláusula ou uma série de catchcláusulas para capturar. catchA cláusula consiste em três partes: palavra-chave catch + um tipo ou objeto entre parênteses + um grupo de declarações entre chaves (usado para lidar com exceções):
catch(iterator_overflow &iof)
{
    
    
	iof.what_happened(log_file);
}
  • O tipo do objeto de exceção será comparado com cada cláusula, uma a umacatch . Se o tipo corresponder, o conteúdo da cláusula será executado. Depois de passar todas as cláusulas catch, o programa normal assume novamente.

Conforme mostrado acima, por meio iofdesse objeto de exceção, chame as funções de membro na classe de exceção what_happened().

  • Quando o tratamento completo da exceção não pode ser concluído, pode ser necessário relançar a exceção para buscar a ajuda de outras cláusulas de captura:
catch(iterator_overflow &iof)
{
    
    
	log_message( iof.what_happened() );
	
	//重新抛出异常,令另一个catch子句接手处理
	throw;
}

Ao relançar, apenas escreva a palavra throw- chave , ela só pode aparecer na catchcláusula, lançar o objeto de exceção capturado novamente e outra cláusula catch com o mesmo tipo assumirá o processamento.

  • Se quisermos capturar qualquer tipo de exceção, podemos usar um método pega-tudo:
//在异常声明部分指定省略号
catch(...)
{
    
    
	log_message( "exception of unknown type" );
	//清理(clean up)然后退出...
}
  • Exceção de refinamento: A catchcláusula deve ser trygerada correspondendo ao bloco. tryO bloco começa com uma palavra-chave try, seguida por uma série de instruções do programa entre colchetes. catchA cláusula é colocada tryno final do bloco, o que significa que se tryocorrer alguma exceção no bloco, ela será catchtratada pela cláusula seguinte .
  • Depois que a função lança uma exceção, o mecanismo de tratamento de exceção começa a verificar onde a exceção é lançada e determinar se ela está localizada no trybloco? Se for, verifique acatch cláusula correspondente para ver se ela tem a capacidade de lidar com essa exceção. Em caso afirmativo, a exceção será tratada e o programa continuará a ser executado (começando da catchprimeira linha da instrução após a cláusula executada )) .
  • Se não estiver no trybloco, o mecanismo de tratamento de exceções terá o direito de executar a função afinal, e o conteúdo restante não será executado. Mas o mecanismo de tratamento de exceções continuará a procurar catchcláusulas que correspondam ao tipo no lado da chamada da função .
  • Se a cadeia de chamada de função for continuamente desfeita, até que main()nenhuma catchcláusula adequada seja encontrada , C ++ estipula que todas as exceções devem ser tratadas, portanto, chama a biblioteca padrão fornecida terminate()- seu comportamento padrão é interromper a execução de todo o programa.
  • Se uma instrução pode causar uma exceção e não está no trybloco, a exceção não deve ser capturada nesta função.
  • Nem toda função deve lidar com todas as exceções possíveis.
  • Quando ocorre tryuma exceção em um bloco de função , mas não há uma catchcláusula correspondente para capturá-la, a função será interrompida e o mecanismo de tratamento de exceção assumirá, rastreará todo o caminho ao longo da cadeia de chamada de função e procurará catchcláusulas que atender às condições .
  • Diante de qualquer exceção C ++ lançada, você pode encontrar uma throwexpressão correspondente em algum lugar do programa .
  • Não confunda exceções C ++ com exceções de hardware, como falha de segmentação ou erro de barramento.
  • Nos seguintes erros de função, não há garantia de que os recursos alocados no início da execução da função serão eventualmente liberados. Se process () lançar uma exceção, as duas instruções subsequentes para liberar recursos não serão executadas.
extern Mutex m;
void f()
{
    
    
	//请求资源
	int *p = new int;
	m.acquire();
	
	process(p);
	
	//释放资源
	m.release();
	delete p;
}
  • Você pode adicionar um bloco try e a cláusula catch correspondente. A cláusula catch captura todas as exceções, libera recursos e relança as exceções. (Mas o código do programa usado para liberar recursos deve aparecer duas vezes (deve haver depois de pegar e pegar))
  • Gerenciamento de recursos (gerenciamento de recursos): as solicitações de recursos são feitas durante a fase de inicialização.
  • Para o objeto, a operação de inicialização ocorre no construtor e a solicitação de recurso também deve ser concluída no construtor. A liberação de recursos deve ser concluída no destruidor.
#include <memory>
void f()
{
    
    
	auto_ptr<int> p(new int);
	MutexLock ml(m);
	process(p);
	//p和ml的destructor会在此处被调用
}
  • Antes que o mecanismo de tratamento de exceções termine uma função, C ++ garante que o destruidor de todos os objetos locais na função será chamado!
  • auto_ptrÉ o modelo de classe fornecido pela biblioteca padrão. Ele excluirá automaticamente os newobjetos alocados por expressões. Antes de usá-lo, inclua o arquivo de cabeçalho #include <memory>, que sobrecarrega o *operador derefrence ( ) e o operador arrow ( ->), para que possa ser usado como um auto_ptrobjeto ponteiro normal .
auto_ptr<string> aps(new string("hello"));
string *ps = new string("hello");
	
if((aps -> size() == ps -> size()) && (*aps == *ps))
	//true
  • Se a newexpressão não puder alocar memória suficiente do espaço livre do programa, bad_allocum objeto de exceção será lançado .
  • Se você quiser suprimir o lançamento da bad_allocexceção, poderá ptext = new (nothrow) vector<string>;fazê- lo ; portanto, se a newoperação falhar, ela retornará 0. Qualquer pessoa ptextdeve verificar se é antes de usá- lo 0.
  • catch(bad_alloc)Não declarou nenhum objeto, apenas estava interessado no tipo de exceção capturada e não tinha a intenção de realmente manipular o objeto na cláusula catch.
  • A biblioteca padrão define um conjunto de sistema de classes de exceção, cuja raiz é uma classe base abstrata exception. exceptionA declaração possui uma what()função virtual que retorna const char *para indicar a descrição do texto da exceção sendo lançada.#include <exception>
  • Você pode integrar sua própria escrita iterator_overflowao exceptionsistema de classes padrão e deve fornecer sua própria what(), para que possa ser capturada por qualquer programa que pretenda capturar a exceção da classe base abstrata.
//捕获exception的所有派生类
catch( const exception &ex)
{
    
    
	cerr << ex.what() << endl;
}
  • A seguir está iterator_overflowcomo what()conseguir isso.
//运用ostringstream对象对输出信息进行格式化
#include <sstream>
#include <string>

const char* iterator_overflow::
what() const
{
    
    
	ostringstream ex_msg;
	static string msg;
	
	//将输出信息写到内存中的 ostringstream对象之中
	//将整数值转为字符串表示
	
	ex_msg << "Internal error: current index "
		   << _index << "exceeds maximum bound: "
		   << _max;
	
	//萃取出string对象
	msg = ex_msg.str();
	
	//萃取出const char*表达式
	return msg.c_str(); 
} 
  • ostringstreamA classe fornece operações de saída na memória e saídas para um stringobjeto. Pode automaticamente _index, _maxesse objeto é convertido para a sequência numérica correspondente, independentemente do armazenamento, algoritmo de conversão outras questões #include <sstream>.
  • ostringstreamUma função de membro fornecida str()pode retornar o objeto string correspondente ao objeto.
  • A função de conversão fornecida pela classe string c_str()retorna uma string de estilo C.
  • A biblioteca iostream também oferece istringstreamclasses correspondentes . Converta a representação de string de dados não string em seu tipo real.
  • ifstreamOs parâmetros aceitos pelo construtor const char*não são string.

Acho que você gosta

Origin blog.csdn.net/pppppppyl/article/details/114383013
Recomendado
Clasificación