一直没有搞明白C++的异常处理问题,今天认真研究了一下,终于明白了.
1、异常的匹配规则: 对于一个异常E和一个带有T或T&参数的handler,符合下面的条件可以进行匹配: T和E是同一类型(const 和volatile被忽略) T是E的没有歧义的公共基类 如果E和T都是指针类型,当二者的类型相同时可以进行匹配或者E所指向对象的类型公有无歧义的继承自T指向对象的类型。
1、异常的匹配规则: 对于一个异常E和一个带有T或T&参数的handler,符合下面的条件可以进行匹配: T和E是同一类型(const 和volatile被忽略) T是E的没有歧义的公共基类 如果E和T都是指针类型,当二者的类型相同时可以进行匹配或者E所指向对象的类型公有无歧义的继承自T指向对象的类型。
2、throw 一个对象时,表达式会发生许多个步骤 1 throw 表达式通过调用类类型pushOnFull 的构造函数创建一个该类的临时对象(这个临时对象的存放位置与平台有很大的关系,有的 放在单独的异常栈中。有的放在一块受保护的内存区域,这个临时对象直到异常被处理完后才会被释放。)。 2 创建一个pushOnFull 类型的异常对象并传递给异常处理代码该异常对象是第1 步throw 表达式创建的临时对象的拷贝它通过调用pushOnFull 类的拷贝构造函数而创建 3 在开始查找异常处理代码之前在第1 步中由throw 表达式创建的临时对象被销毁 3、在进行异常捕获声明的时候最好是使用引用类型,如catch(MyException &myExcept),如果声明为对象的形式,则会造成对象的多次拷贝。 造成内存的浪费。而如果采用指针的形式,则要显示的删除抛出的在堆中分配的对象,因为这时的临时对象只是一个指针,所以要求在 catch中显式的delete这块内存。MFC的异常处理则是用的这种方法。 // Normal program statements ... try { // Execute some code that might throw an exception. } catch( CException* e ) { // Handle the exception here. // "e" contains information about the exception. e->Delete(); } //分析 CFile::CFile(LPCTSTR lpszFileName, UINT nOpenFlags) { ASSERT(AfxIsValidString(lpszFileName)); CFileException e; if (!Open(lpszFileName, nOpenFlags, &e)) AfxThrowFileException(e.m_cause, e.m_lOsError, e.m_strFileName); } | | | ^ void AFXAPI AfxThrowFileException(int cause, LONG lOsError, LPCTSTR lpszFileName /* == NULL */) { #ifdef _DEBUG LPCSTR lpsz; if (cause >= 0 && cause < _countof(rgszCFileExceptionCause)) lpsz = rgszCFileExceptionCause[cause]; else lpsz = szUnknown; TRACE3("CFile exception: %hs, File %s, OS error information = %ld.\n", lpsz, (lpszFileName == NULL) ? _T("Unknown") : lpszFileName, lOsError); #endif THROW(new CFileException(cause, lOsError, lpszFileName)); } | | | ^ #define THROW(e) throw e //这是虚函数 void CException::Delete() { // delete exception if it is auto-deleting if (m_bAutoDelete > 0) { #ifdef _DEBUG m_bReadyForDelete = TRUE; #endif delete this; } }