一、catch语句中可以抛出异常
(1)、catch语句中抛出的异常需要外层的try...catch...捕获
(1)、catch中捕获的异常可以被重新解释后抛出
(2)、工程中使用这样的方式统一异常类型
#include <iostream> using namespace std; //演示在catch块中可以抛出异常 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 << "Call func(int i)" << endl; } //以下是我们的私有库,当中使用到了第3方的库,这里需要将第3方库的 //异常类型统一成我们的异常信息格式 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() { Demo(); cout << endl; try { MyFunc(11); } catch(const char* cs) { cout << "Exception info: " << cs << endl; } return 0; }; /*输出结果: Inner:catch(...) Outer:catch(...) Exception info: Timeout Exception */
二、类类型中的异常
1、异常的类型可以是自定义的类类型
2、对于类类型的异常匹配依旧是自上而下的严格匹配
3、赋值兼容性原则在匹配中依然适用
4、一般而言
(1)、匹配子类异常的catch放在上部
(2)、匹配父类异常的catch放在下部
5、工程中的应用
(1)、在工程中会定义一系列的异常类
(2)、每个类代表工程中可能出现的一种异常类型
(3)、代码复用时可能需要重解释不同的异常类
(4)、在定义catch语句块时推荐使用引用作为参数(减少拷贝构造的调用以提高效率)
#include <iostream> #include <string> 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 //考虑const Exception对象时,函数加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 << "Call func(int i)" << endl; } //以下是我们的私有库,当中使用到了第3方的库,这里需要将第3方库的 //异常类型统一成我们的异常信息格式 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) //注意使用引用以防止拷贝,提高效率 { 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 */
三、标准库中的异常
1、c++标准库中提供了实用异常类族
2、标准库中的异常都是从exception类派生的
3、exception类有两个主要的分支
(1)、logic_error:常用于程序中的可避免逻辑错误
(2)、runtime_error:常用于程序中的无法避免的恶性错误
//Array.h
#ifndef _ARRAY_H_ #define _ARRAY_H_ #include <stdexcept> //引入异常类 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<T, N>::length() const { return N; } template < typename T, int N> bool Array<T, N>::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<T, N>::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<T, N>::operator[](int index) { if((0 <= index) && (index < N)) { return m_array[index]; } else { //out_of_range是标准库中的异常类 throw out_of_range("T& Array<T, N>::operator[](int index)"); //参数为抛出的异常信息 } } template < typename T, int N> T Array<T, N>::operator[](int index) const { if((0 <= index) && (index < N)) { return m_array[index]; } else { //out_of_range是标准库中的异常类 throw out_of_range("T Array<T, N>::operator[](int index) const"); } } template < typename T, int N> Array<T, N>::~Array() { } #endif
//HeapArray.h
#ifndef _HEAPARRAY_H_ #define _HEAPARRAY_H_ #include <stdexcept> //引入异常类 using namespace std; template < typename T> class HeapArray { private: int m_length; T* m_pointer; HeapArray(int len); HeapArray(const HeapArray<T>& obj); bool construct(); public: static HeapArray<T>* NewInstance(int length); static void ReleaseInstance(const HeapArray<T>* pointer); 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<T>& self() const; HeapArray<T>& self(); //与上面函数构成重载关系 ~HeapArray(); }; template <typename T> HeapArray<T>::HeapArray(int len) { m_length = len; } template <typename T> HeapArray<T>::HeapArray(const HeapArray<T>& obj) { m_pointer = obj.m_pointer; m_length = obj.m_length; } template <typename T> bool HeapArray<T>::construct() { m_pointer = new T[m_length]; return m_pointer != NULL; } template <typename T> HeapArray<T>* HeapArray<T>::NewInstance(int len) { HeapArray<T>* ret = new HeapArray<T>(len); if (!(ret && ret->construct())) { delete ret; ret = 0; } return ret; } template <typename T> void HeapArray<T>::ReleaseInstance(const HeapArray<T>* pointer) { delete pointer; } template <typename T> int HeapArray<T>::length() const { return m_length; } template <typename T> bool HeapArray<T>::get(int index, T& value) { bool ret = ((0 <= index)&&(index < m_length)); if(ret) { value = m_pointer[index]; } return ret; } template <typename T> bool HeapArray<T>::set(int index, T value) { bool ret = ((0 <= index)&&(index < m_length)); if(ret) { m_pointer[index] = value ; } return ret; } template <typename T> T& HeapArray<T>::operator[](int index) { if((0 <= index)&&(index < m_length)) { return m_pointer[index]; } else { throw out_of_range("T& HeapArray<T>::operator[](int index)"); } } template <typename T> T HeapArray<T>::operator[](int index) const { if((0 <= index)&&(index < m_length)) { return m_pointer[index]; } else { throw out_of_range("T HeapArray<T>::operator[](int index) const"); } } template <typename T> HeapArray<T>& HeapArray<T>::self() const { return *this; } template <typename T> HeapArray<T>& HeapArray<T>::self() { return *this; } template <typename T> HeapArray<T>::~HeapArray() { delete[] m_pointer; } #endif
//main.cpp
#include <iostream> #include <string> #include <memory> //for auto_ptr #include "Array.h" #include "HeapArray.h" using namespace std; void TestArray() { Array<int, 5> a; for(int i=0; i<a.length(); i++) { a[i] = i; } for (int i=0; i<10; i++) { cout << a[i] << endl; } } void TestHeapArray() { //使用智能指针,目的是自动释放堆空间 auto_ptr< HeapArray<double> > pa(HeapArray<double>::NewInstance(5)); if(pa.get() != NULL) { HeapArray<double>& array = pa->self(); for(int i=0; i<array.length(); i++) { array[i] = i; } for (int i=0; i<10; i++) { cout << array[i] << endl; } } } int main() { //试验1:观察异常出错的信息 TestArray(); cout << endl; TestHeapArray(); //试验2: 观察异常出错的信息 // try // { // TestArray(); // cout << endl; // TestHeapArray(); // } // catch(...) // { // cout << "Exception" << endl; // } return 0; };
四、小结
(1)、catch语句块中可以抛出异常
(2)、异常的类型是可以自定义的类类型
(3)、赋值兼容性原则在异常匹配中依然适用
(4)、标准库中的异常都是从exception类派生的
时间: 2024-11-06 11:41:11