Siete, manejo de excepciones

  • 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 throwexpresiones 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 throwexpresió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 catchcláusulas para capturar. catchLa cláusula consta de tres partes: palabra clave catch + 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 unacatch . 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 iofeste objeto de excepción, llame a las funciones miembro en la clase de excepción what_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 la catchclá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 catchcláusula debe trygenerarse correspondiente al bloque. tryEl bloque comienza con una palabra clave try, seguida de una serie de declaraciones de programa entre llaves. catchLa cláusula se coloca tryal final del bloque, lo que significa que si tryocurre alguna excepción en el bloque, será catchmanejada 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 trybloque. 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 desde catchla primera línea de la declaración después de la cláusula ejecutada )) .
  • Si no está en el trybloque, 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á buscando catchclá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 una catchclá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 trybloque, la excepción no debe capturarse en esta función.
  • No todas las funciones deben manejar todas las posibles excepciones.
  • Cuando ocurre tryuna excepción en un bloque de funciones , pero no hay una catchclá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á catchcláusulas que Cumplir las condiciones .
  • Ante cualquier excepción de C ++ que se lance, puede encontrar una throwexpresió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_ptrEs la plantilla de clase proporcionada por la biblioteca estándar. Eliminará automáticamente los newobjetos 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 un auto_ptrObjeto puntero normal .
auto_ptr<string> aps(new string("hello"));
string *ps = new string("hello");
	
if((aps -> size() == ps -> size()) && (*aps == *ps))
	//true
  • Si la newexpresión no puede asignar suficiente memoria del espacio libre del programa, se lanzará bad_allocun objeto de excepción.
  • Si desea evitar bad_allocque se lance la excepción, puede ptext = new (nothrow) vector<string>;hacerlo, por lo que si la newoperación falla, regresará 0. Cualquiera ptextdebería comprobar si es así antes de usarlo 0.
  • 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. exceptionLa declaración tiene una what()función virtual que regresa const char *para indicar la descripción de texto de la excepción que se lanza.#include <exception>
  • Puede integrar su propia escritura iterator_overflowen el exceptionsistema de clases estándar y debe proporcionar la suya propia what(), 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_overflowcómo what()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(); 
} 
  • ostringstreamLa clase proporciona operaciones de salida en memoria y salidas a un stringobjeto. Puede automáticamente _index, _maxtal objeto se convierte en la cadena numérica correspondiente independientemente del almacenamiento, el algoritmo de conversión otros problemas #include <sstream>.
  • ostringstreamUna función miembro proporcionada str()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 istringstreamclases correspondientes . Convierta la representación de cadena de datos que no son de cadena a su tipo real.
  • ifstreamLos parámetros aceptados por el constructor const char*no lo son string.

Supongo que te gusta

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