- Mecanismo de manejo de excepciones (facilidad de manejo de excepciones): Como diseñadores, no sabemos qué tan dañino es un posible problema para todo el programa, solo el usuario de esta función conoce la gravedad del problema. Por lo tanto, nuestra responsabilidad es notificar al usuario y decirle lo sucedido El mecanismo de manejo de excepciones se utiliza para completar la tarea de notificación.
- El mecanismo de manejo de excepciones incluye: identificación de excepciones y problema + método de manejo de excepciones.
- Después de que ocurre la excepción, se suspende la ejecución del programa normal y el mecanismo de manejo de excepciones comienza a buscar ubicaciones en el programa que sean capaces de manejar la excepción. Después de que se procesa la excepción, la ejecución del programa continuará (reanudará) y continuará ejecutándose desde el punto de manejo de la excepción .
- Lanzar (lanzar) excepciones: las
throw
expresiones parecen llamadas a funciones, las excepciones son algún tipo de objeto, la mayoría de las veces pertenecen a una clase de excepción específica (pueden formar un sistema de herencia).
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;
};
- La
throw
expresión anterior llamará directamente al constructor con dos parámetros. También puede especificar el nombre del objeto lanzado:
if(_index > Triangular::_max_elems)
{
iterator_overflow ex(_index, Triangular::_max_elems);
throw ex;
}
- Capturar excepciones: use una sola cláusula o una serie de
catch
cláusulas para capturar.catch
La cláusula consta de tres partes: palabra clavecatch
+ un tipo u objeto entre paréntesis + un grupo de declaraciones entre llaves (utilizadas para manejar excepciones):
catch(iterator_overflow &iof)
{
iof.what_happened(log_file);
}
- El tipo de objeto de excepción se comparará con cada cláusula una por una
catch
. Si el tipo coincide, se ejecutará el contenido de la cláusula. Después de pasar todas las cláusulas de captura, el programa normal vuelve a tomar el control.
Como se muestra arriba, a través de
iof
este objeto de excepción, llame a las funciones miembro en la clase de excepciónwhat_happened()
.
- Cuando no se puede completar el manejo completo de la excepción, puede ser necesario volver a lanzar la excepción para buscar la ayuda de otras cláusulas de captura:
catch(iterator_overflow &iof)
{
log_message( iof.what_happened() );
//重新抛出异常,令另一个catch子句接手处理
throw;
}
Al volver a lanzar, simplemente escriba la palabra clave
throw
, solo puede aparecer en lacatch
cláusula, lanzar el objeto de excepción detectado nuevamente y otra cláusula catch con el mismo tipo se hará cargo del procesamiento.
- Si queremos detectar cualquier tipo de excepción, podemos usar un método general:
//在异常声明部分指定省略号
catch(...)
{
log_message( "exception of unknown type" );
//清理(clean up)然后退出...
}
- Excepción de refinamiento: la
catch
cláusula debetry
generarse correspondiente al bloque.try
El bloque comienza con una palabra clavetry
, seguida de una serie de declaraciones de programa entre llaves.catch
La cláusula se colocatry
al final del bloque, lo que significa que sitry
ocurre alguna excepción en el bloque, serácatch
manejada por la siguiente cláusula. - Después de que la función arroja una excepción, el mecanismo de manejo de excepciones comienza a verificar dónde se lanza la excepción y determina si está ubicada en el
try
bloque. Si es así, verifique lacatch
cláusula correspondiente para ver si tiene la capacidad de manejar esta excepción. Si es así, la excepción será manejada y el programa continuará ejecutándose (comenzando desdecatch
la primera línea de la declaración después de la cláusula ejecutada )) . - Si no está en el
try
bloque, el mecanismo de manejo de excepciones tendrá derecho a ejecutar la función después de todo, y el contenido restante no se ejecutará. Pero el mecanismo de manejo de excepciones continuará buscandocatch
cláusulas que coincidan con el tipo en el lado llamante de la función . - Si la cadena de llamadas a la función se desenreda continuamente, hasta que
main()
no se encuentre unacatch
cláusula adecuada , C ++ estipula que se deben manejar todas las excepciones, por lo que llama a la biblioteca estándar proporcionada;terminate()
su comportamiento predeterminado es interrumpir la ejecución de todo el programa. - Si una declaración puede causar una excepción y no está en el
try
bloque, la excepción no debe capturarse en esta función. - No todas las funciones deben manejar todas las posibles excepciones.
- Cuando ocurre
try
una excepción en un bloque de funciones , pero no hay unacatch
cláusula correspondiente para detectarla, la función se interrumpirá y el mecanismo de manejo de excepciones tomará el control, rastreará a lo largo de la cadena de llamadas a la función y buscarácatch
cláusulas que Cumplir las condiciones . - Ante cualquier excepción de C ++ que se lance, puede encontrar una
throw
expresión correspondiente en algún lugar del programa . - No confunda las excepciones de C ++ con excepciones de hardware como fallas de segmentación o errores de bus.
- Los siguientes errores de función, no hay garantía de que los recursos asignados al comienzo de la ejecución de la función finalmente se liberen. Si process () arroja una excepción, las dos declaraciones subsiguientes para liberar recursos no se ejecutarán.
extern Mutex m;
void f()
{
//请求资源
int *p = new int;
m.acquire();
process(p);
//释放资源
m.release();
delete p;
}
- Puede agregar un bloque try y la cláusula catch correspondiente. La cláusula catch captura todas las excepciones, libera recursos y vuelve a generar las excepciones. (Pero el código del programa utilizado para liberar recursos debe aparecer dos veces (debe haber después de la captura y la captura))
- Gestión de recursos (gestión de recursos): las solicitudes de recursos se realizan durante la fase de inicialización.
- Para el objeto, la operación de inicialización tiene lugar en el constructor y la solicitud de recursos también debe completarse en el constructor. La liberación de recursos debe completarse en el destructor.
#include <memory>
void f()
{
auto_ptr<int> p(new int);
MutexLock ml(m);
process(p);
//p和ml的destructor会在此处被调用
}
- Antes de que el mecanismo de manejo de excepciones termine una función, C ++ garantiza que se llamará al destructor de todos los objetos locales de la función.
auto_ptr
Es la plantilla de clase proporcionada por la biblioteca estándar. Eliminará automáticamente losnew
objetos asignados por expresiones. Antes de usarlo, incluya el archivo de encabezado#include <memory>
, que sobrecarga el*
operador derefrence ( ) y el operador arrow (->
), para que pueda usarse como unauto_ptr
Objeto puntero normal .
auto_ptr<string> aps(new string("hello"));
string *ps = new string("hello");
if((aps -> size() == ps -> size()) && (*aps == *ps))
//true
- Si la
new
expresión no puede asignar suficiente memoria del espacio libre del programa, se lanzarábad_alloc
un objeto de excepción. - Si desea evitar
bad_alloc
que se lance la excepción, puedeptext = new (nothrow) vector<string>;
hacerlo, por lo que si lanew
operación falla, regresará0
. Cualquieraptext
debería comprobar si es así antes de usarlo0
. catch(bad_alloc)
No declaró ningún objeto, solo estaba interesado en el tipo de excepción detectada y no tenía la intención de manipular realmente el objeto en la cláusula catch.- La biblioteca estándar define un conjunto de sistemas de clases de excepción, cuya raíz es una clase base abstracta
exception
.exception
La declaración tiene unawhat()
función virtual que regresaconst char *
para indicar la descripción de texto de la excepción que se lanza.#include <exception>
- Puede integrar su propia escritura
iterator_overflow
en elexception
sistema de clases estándar y debe proporcionar la suya propiawhat()
, para que pueda ser capturada por cualquier programa que intente capturar la excepción de clase base abstracta.
//捕获exception的所有派生类
catch( const exception &ex)
{
cerr << ex.what() << endl;
}
- Lo siguiente es
iterator_overflow
cómowhat()
lograrlo.
//运用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
La clase proporciona operaciones de salida en memoria y salidas a unstring
objeto. Puede automáticamente_index
,_max
tal objeto se convierte en la cadena numérica correspondiente independientemente del almacenamiento, el algoritmo de conversión otros problemas#include <sstream>
.ostringstream
Una función miembro proporcionadastr()
puede devolver el objeto de cadena correspondiente al objeto.- La función de conversión proporcionada por la clase de cadena
c_str()
devuelve una cadena de estilo C. - La biblioteca de iostream también proporciona las
istringstream
clases correspondientes . Convierta la representación de cadena de datos que no son de cadena a su tipo real. ifstream
Los parámetros aceptados por el constructorconst char*
no lo sonstring
.