使用throw語句在可能發生異常的程序出拋出異常代碼,在執行程序是使用try語句執行,並使用catch語句捕獲異常,執行異常之后的操作。
與C語言的setjmp和longjmp相比,他不必在每一次語句運行之后都使用一次異常處理代碼,並且,它不容易忽略異常。
throw在拋出異常時,不僅可以拋出內置類型的異常,也可以拋出自定義類型的異常。
#include <iostream> #include<string> using namespace std; class MyExpression{ public: MyExpression(const char* message) :message_(message) { cout << "MyExpression..." << endl; } MyExpression(const MyExpression & other)//拷貝構造函數; :message_(other.message_) { cout << "copy MyExpression..." << endl; } ~MyExpression(){ cout << "~MyExpression" << endl; } string WhatError() { return message_.c_str(); } private: string message_; }; double Divide(double a, double b){ if (b == 0){ MyExpression e("division is zero"); throw e; } else return a / b; } int main(){ try{ cout << Divide(5.0, 0.0) << endl; } catch (MyExpression& e){ cout << e.WhatError() << endl; } return 0; }
這個例子中可以看出,拋出自定義類型的執行步驟是首先構造一個自定義類型,然后拷貝,然后析構局部對象,然后捕獲異常,最后析構拷貝的自定義類型。
這個過程與調用函數的流程相似,當返回一個對象的時候會調用拷貝構造函數。當在return處直接構造函數是,就不會調用拷貝構造函數了。比如return MyExpression(“string”),同樣throw MyExpression(“string”)時也不會調用拷貝構造函數。
在異常被捕獲之前,局部對象被銷毀的過程稱之為棧展開。一個catch就是一個異常處理器,一個異常處理器只能捕獲一種類型的異常。異常匹配時,捕獲的類型不做類型的轉換,也就是說無法使用double類型的異常處理器捕獲int類型的異常。catch(...表示可以捕獲任意類型的異常)