- 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
throw
expressõ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
throw
expressã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
catch
cláusulas para capturar.catch
A cláusula consiste em três partes: palavra-chavecatch
+ 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 uma
catch
. 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
iof
desse objeto de exceção, chame as funções de membro na classe de exceçãowhat_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 nacatch
clá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
catch
cláusula deve sertry
gerada correspondendo ao bloco.try
O bloco começa com uma palavra-chavetry
, seguida por uma série de instruções do programa entre colchetes.catch
A cláusula é colocadatry
no final do bloco, o que significa que setry
ocorrer alguma exceção no bloco, ela serácatch
tratada 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
try
bloco? 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 dacatch
primeira linha da instrução após a cláusula executada )) . - Se não estiver no
try
bloco, 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 procurarcatch
clá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()
nenhumacatch
cláusula adequada seja encontrada , C ++ estipula que todas as exceções devem ser tratadas, portanto, chama a biblioteca padrão fornecidaterminate()
- 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
try
bloco, 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
try
uma exceção em um bloco de função , mas não há umacatch
clá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ácatch
cláusulas que atender às condições . - Diante de qualquer exceção C ++ lançada, você pode encontrar uma
throw
expressã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 osnew
objetos 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 umauto_ptr
objeto ponteiro normal .
auto_ptr<string> aps(new string("hello"));
string *ps = new string("hello");
if((aps -> size() == ps -> size()) && (*aps == *ps))
//true
- Se a
new
expressão não puder alocar memória suficiente do espaço livre do programa,bad_alloc
um objeto de exceção será lançado . - Se você quiser suprimir o lançamento da
bad_alloc
exceção, poderáptext = new (nothrow) vector<string>;
fazê- lo ; portanto, se anew
operação falhar, ela retornará0
. Qualquer pessoaptext
deve verificar se é antes de usá- lo0
. 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
.exception
A declaração possui umawhat()
função virtual que retornaconst char *
para indicar a descrição do texto da exceção sendo lançada.#include <exception>
- Você pode integrar sua própria escrita
iterator_overflow
aoexception
sistema de classes padrão e deve fornecer sua própriawhat()
, 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_overflow
comowhat()
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();
}
ostringstream
A classe fornece operações de saída na memória e saídas para umstring
objeto. Pode automaticamente_index
,_max
esse objeto é convertido para a sequência numérica correspondente, independentemente do armazenamento, algoritmo de conversão outras questões#include <sstream>
.ostringstream
Uma função de membro fornecidastr()
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
istringstream
classes correspondentes . Converta a representação de string de dados não string em seu tipo real. ifstream
Os parâmetros aceitos pelo construtorconst char*
não sãostring
.