C++中的异常处理教程(下)
程序员文章站
2023-08-31 19:34:59
一、c++中的异常处理
catch语句块中可以抛出异常
catch中捕获的异常可以被重新解释后抛出
工程开发中使用这样的方式统一异常类型
实验:异常的重新解释
#include
using...
一、c++中的异常处理
catch语句块中可以抛出异常
catch中捕获的异常可以被重新解释后抛出
工程开发中使用这样的方式统一异常类型
实验:异常的重新解释
#include using namespace std; void demo(){ try{ try{ throw 'c'; } catch(int i){ cout <<"inner:catch(int i)" << endl; throw i; } catch(...){ cout << "inner:catch(...)" << endl; throw; } } catch(...){ cout << "outer:catch(...)" << endl; } } /* 假设: 当前的函数式第三方库中的函数,因此,我们无法修改源代码 函数名: void func(int i) 抛出异常的类型: int -1 ==> 参数异常 -2 ==> 运行异常 -3 ==> 超时异常 */ void func(int i){ if(i < 0){ throw -1; } if(i > 100){ throw -2; } if(i == 11){ throw -3; } cout << "run func..." << endl; } void myfunc(int i){ try{ func(i); } catch(int i){ switch(i){ case -1: throw "invalid parameter"; break; case -2: throw "runtime exception"; break; case -3: throw "timeout exception"; break; } } } int main(int argc,char *argv[]){ try{ myfunc(11); } catch(const char* cs){ cout << "exception info:" << cs << endl; } return 0; }
打印结果:
exception info:timeout exception异常的类型可以是自定义类类型 对于类类型异常的匹配依旧是自上而下严格匹配 赋值兼容性原则在异常匹配中依然适用 一般而言
匹配子类异常的catch放在上部 匹配父类异常的catch放在下部
在工程中会定义一系列的异常类 每个类代表工程中可能出现的一种异常类型 代码复用时可能需要重解释不同的异常类 在定义catch语句块时推荐使用引用作为参数
编程实验:类类型的异常
#include #include using namespace std; class base{ }; class exception : public base{ int m_id; string m_desc; public: exception(int id,string desc){ m_id = id; m_desc = desc; } int id() const{ return m_id; } string description() const{ return m_desc; } }; /* 假设: 当前的函数式第三方库中的函数,因此,我们无法修改源代码 函数名: void func(int i) 抛出异常的类型: int -1 ==> 参数异常 -2 ==> 运行异常 -3 ==> 超时异常 */ void func(int i){ if(i < 0){ throw -1; } if(i > 100){ throw -2; } if(i == 11){ throw -3; } cout <<"run func..." << endl; } void myfunc(int i){ try{ func(i); } catch(int i){ switch(i){ case -1: throw exception(-1,"invalid parameter"); break; case -2: throw exception(-2,"runtime exception"); break; case -3: throw exception(-3,"timeout exception"); break; } } } int main(){ try{ myfunc(11); } catch(const exception& e){ //务必注意上一层catch抛出的类型 cout << "exception info:" << endl; cout << " id:" << e.id() << endl; cout << " description:" << e.description() << endl; } catch(const base& e){ cout << "catch(const base& e)" << endl; } return 0; }
打印结果:
exception info: id:-3 description:timeout exception
c++标准库中提供了实用异常类族 标准库中的异常都是从exception类派生的 exception类有两个主要的分支
logic_error 常用于程序中的可避免的逻辑错误 runtime_error 常用于程序中无法避免的恶性错误
编程实验:标准库中的异常使用
代码一:array.h
#ifndef _array_h_ #define _array_h_ #include //注意该头文件 using namespace std; template < typename t, int n > class array{ t m_array[n]; public: int length() const; bool set(int index, t value); bool get(int index, t& value); t& operator[] (int index); t operator[] (int index) const; virtual ~array(); }; template < typename t, int n > int array::length() const{ //注意加const return n; } template < typename t, int n > bool array::set(int index, t value){ bool ret = (0 <= index) && (index < n); if( ret ){ m_array[index] = value; } return ret; } template < typename t, int n > bool array::get(int index, t& value){ bool ret = (0 <= index) && (index < n); if( ret ){ value = m_array[index]; } return ret; } template < typename t, int n > t& array::operator[] (int index){ if( (0 <= index) && (index < n) ){ return m_array[index]; } else{ throw out_of_range("t& array::operator[] (int index)");//设置异常处理 } } template < typename t, int n > t array::operator[] (int index) const{ if( (0 <= index) && (index < n) ){ return m_array[index]; } else{ throw out_of_range("t array::operator[] (int index) const"); } } template < typename t, int n > array::~array() { } #endif
代码二:heaparray.h
#ifndef _heaparray_h_ #define _heaparray_h_ #include using namespace std; template < typename t > class heaparray{ private: int m_length; t* m_pointer; heaparray(int len); heaparray(const heaparray& obj); bool construct(); public: static heaparray* newinstance(int length); int length() const; bool get(int index, t& value); bool set(int index ,t value); t& operator [] (int index); t operator [] (int index) const; heaparray& self(); const heaparray& self() const; ~heaparray(); }; template < typename t > heaparray::heaparray(int len){ m_length = len; } template < typename t > bool heaparray::construct(){ m_pointer = new t[m_length]; return m_pointer != null; } template < typename t > heaparray* heaparray::newinstance(int length){ heaparray* ret = new heaparray(length); if( !(ret && ret->construct()) ) { delete ret; ret = 0; } return ret; } template < typename t > int heaparray::length() const{ return m_length; } template < typename t > bool heaparray::get(int index, t& value){ bool ret = (0 <= index) && (index < length()); if( ret ){ value = m_pointer[index]; } return ret; } template < typename t > bool heaparray::set(int index, t value) { bool ret = (0 <= index) && (index < length()); if( ret ) { m_pointer[index] = value; } return ret; } template < typename t > t& heaparray::operator [] (int index){ if( (0 <= index) && (index < length()) ){ return m_pointer[index]; } else{ throw out_of_range("t& heaparray::operator [] (int index)");//调用标准库异常out_of_range } } template < typename t > t heaparray::operator [] (int index) const{ if( (0 <= index) && (index < length()) ){ return m_pointer[index]; } else{ throw out_of_range("t heaparray::operator [] (int index) const"); } } template< typename t > heaparray& heaparray::self(){ return *this; } template < typename t > const heaparray& heaparray::self() const{ return *this; } template < typename t > heaparray::~heaparray(){ delete[]m_pointer; } #endif
代码三:65-3.cpp
#include #include #include "array.h" #include"heaparray.h" using namespace std; void testarray(){ array a; for(int i = 0;i < a.length();++i){ a[i] = i; } for(int i = 0;i < a.length();++i){ cout << a[i] << endl; } } void testheaparray(){ heaparray* pa = heaparray::newinstance(5); if(pa != null){ heaparray& array = pa->self(); for(int i = 0;i < array.length();++i){ array[i] = i; } for(int i = 0;i < array.length();++i){ cout << array[i] << endl; } } delete pa; } int main(){ try{ testarray(); cout << endl; testheaparray(); } catch(...){ cout << "exception" << endl; } return 0; }
二、总结
catch语句块可以抛出异常 异常的类型可以是自定义类类型 赋值兼容性原则在异常匹配中依然适用 标准库中的异常都是从exception类派生出来的