之前都沒有好好練習過異常,也沒有深入瞭解過,最近在看Thinking In C++中,它的第一章就講述了大量的異常代碼,本以為很簡單,然而在機器上編譯調試了一番,才發現並不是那麼一回事。在執行下面的異常程式中,發現很有些特色(可能老手早就熟悉了),記錄下來, 以便將來查看!程式原始碼為:
//: C01: Unexpcected.cpp
// Exception specifications & unexcepted(),
//{-msc} (doesn't terminate properly)
#include <exception>
#include <iostream>
using namespace std;
class Up...{};
class Fit...{};
void g();
void f(int i) throw(Up,Fit)
...{
switch(i)
...{
case 1: throw Up();
case 2: throw Fit();
}
g();
}
// void g() {} //version 1
void g()
...{
throw 32;
}
void my_unexpected()
...{
cout<<" unexpected exception thrown"<<endl;
exit(0);
}
int main()
...{
set_unexpected(my_unexpected); // Ignores return value
for( int i=1; i<=3; i++)
try
...{
f(i);
}
catch(Up)
...{
cout<<"Up caught"<<endl;
}
catch(Fit)
...{
cout<<"Fit caught"<<endl;
}
return 0;
} /**////:~
整個程式結構非常簡單,set_unexpected函數是exception標頭檔中提供的標準函數,用來設定拋出的異常沒有列在異常規格說明(exception specification)的異常集中調用的unexpected函數(預設)
f 函數申明了異常規格說明集合,但調用了版本2的g 函數,而該函數拋出的異常卻不在f 函數的異常規格說明集合中,因此將預設調用unexpected函數,此處將調用my_unexpected函數。
在VC中調試運行該函數,拋出出錯對話方塊:
之後調試該程式,才驚奇的發現該程式運行順序為
首先執行for語句,然後執行try塊中的f 函數調用,之後拋出Up異常,跳轉到catch(Up)語句處執行,輸出Up caught後,跳轉到return 0語句,之後再執行for語句,再一次迴圈,拋出Fit異常,return 0之後再運行for語句,拋出Debug Error 對話方塊!
原來異常程式的執行是如此的巧妙!
正如文中所說:把try塊嵌入在for,while,do或if塊中,並且觸發異常來試圖解決問題;然後重新測試try塊中的代碼!也就是說,即使其中一個執行過程拋出了異常,for,while,do或if等都能夠繼續執行下去,只針對其中一個過程產生影響,對全域影響並不是很大。
該程式在cygwin中可以被正確編譯運行!說明了VC對標準C++的支援不是很好!