try blocks
-
try blocks
try {...} catch ... catch ...
-
establishes any number of handers
-
not needed if you don't use any handlers
-
shows where you expert to handle exceptions
-
const cycles
exception handlers
-
select exception by type
-
can re-raise exceptions
-
two forms
catch (SomeType v){}//handler code 很像函数 catch(...){}//handler code 处理所有异常,但是得不到异常对象
-
take a single argument(like a formal parameter)
selecting a handler
-
can have any number of handlers
-
handlers are checked in order of appearance 针对每一个catch做下面的 1, 2, 3
- check for exact match
- apply base class conversions
- reference and pointer type,only
- ellipses(...) match all
inheritance can be used to structure exceptions
example:using inheritance
-
hierarchy of exception types
class MathErr{ ... virtual void diagnstic(); }; class OverflowErr:pubic MathErr{...} class UnderflowErr:pubic MathErr{...} class ZeroDivideErr:pubic MathErr{...}
using handlers
try{ //code to expercise math options throw UnderFlowErr }catch(ZeroDivideErr& e){ //handle zero divide cade }catch(MathErr& e){ //handle other math errors }catch(...){ //any other exceptions }
exception specifications
-
declare which exceptions function might raise
-
part of function prototypes
void abc(int a):throw(MathErr){ //约束abc只抛出MathErr异常 ... }
-
not checked at compile time
-
at run time
- if an exceptions not in the list propagates out,the "unexpected" exception is raised
examples
Printer::print(Document&):throw(PrinterOfffLine,BadDocument){ ... PintManager::print(Document&):throw (BadDocument){ //raises or doesn't handle BadDocuement } void googguy():throw(){ // 什么都不抛出 //handle all exceptions } voi average(){}//no spec, no checking }
exceptions and new
-
new does NOT returned 0 on failure
-
new raises a bad_alloc() exception
void func(){ try{ while(1){ char*p = new char[10000]; } }catch(bad_alloc& e) } }
failure in constructors: 构造函数中出现异常
- no return value is possible
- use an "uninitialized flag"
- defer work to an init() function
better throw an exception
if you constructor can't complete,throw an exception 构造没有完成,析构不能调用
- dtors for objects whose ctor didn't complete won't be called
- clean up allocated resources before throwing
#include<iostream>
using namespace std;
class A
{
public:
A() { buf = new char[1024]; delete this; throw 0; }
~A() { delete buf; }
};
int main()
{
A a;//析构没做,但是空间已经收回了,如果析构里有delete相关的,也不能收回空间,a本身不是垃圾,但buf是
A* p = new A();//构造函数没有成功执行,运行不到delete回收空间
delete p;
return 0;
}
//main.cpp
programming with exceptions
prefer catching exceptions by reference
-
throwing/catching by value involves slicing
struct X{} struct Y:pubic X{} try{ throw Y(): }catch(X x){ //was it or Y? }
-
throwing/catching by pointer introduces coupling between normal and handler code:
try{ throw new Y(); }catch(Y* p){ //whoop ,forgot to delete }
catch exceptions by reference: 推荐做法
struct B{ virtual void print(){...} } struct D : public B{...}; try { throw D("D error"); } catch(B& b){ b.print() // print D's error }