C++ 異常處理(三) exception類
1,exception
標頭檔案:
#include <exception>
C++ 可以把它用作其它異常類的基類。
程式碼可以引發exception異常,也可以把exception用作基類,
在從exception派生而來的類中重新定義一個名為what()的虛擬成員函式,
它返回一個字串,該字串隨實現而異。
如果不想以不同的方式捕獲這些派生來的異常,可以在同一個基類處理程式中捕獲它們:#include <exception> class bad_hmean : public std::exception { public: const char* what() { return "bad arguments to hmean()"; } // ... }; class bad_gmean : public std::exception { public: const char* what() { return "bad arguments to gmean()"; } // ... };
try{
//...
}
catch(std::exception& e)
{
cout << e.what() << endl;
// ...
}
否則,應分別捕獲它們。
C++庫定義了很多基於exception的異常型別。
1,stdexcept 異常類
該檔案定義了logic_error和runtime_error類,它們都是以公有類從exception派生而來的。
每個類所在的標頭檔案在圖下方標識出來.
標準異常類的成員:
① 在上述繼承體系中,每個類都有提供了建構函式、複製建構函式、和賦值操作符過載。
② logic_error類及其子類、runtime_error類及其子類,它們的建構函式是接受一個string型別的形式引數,用於異常資訊的描述;
③ 所有的異常類都有一個what()方法,返回const char* 型別(C風格字串)的值,描述異常資訊。
異常名稱 |
描述 |
exception | 所有標準異常類的父類 |
bad_alloc | 當operator new and operator new[],請求分配記憶體失敗時 |
bad_exception | 這是個特殊的異常,如果函式的異常丟擲列表裡聲明瞭bad_exception異常,當函式內部丟擲了異常丟擲列表中沒有的異常,這是呼叫的unexpected函式中若丟擲異常,不論什麼型別,都會被替換為bad_exception型別 |
bad_typeid |
使用typeid操作符,操作一個NULL指標,而該指標是帶有虛擬函式的類,這時丟擲bad_typeid異常 |
bad_cast | 使用dynamic_cast轉換引用失敗的時候 |
ios_base::failure | io操作過程出現錯誤 |
logic_error | 邏輯錯誤,可以在執行前檢測的錯誤 |
runtime_error | 執行時錯誤,僅在執行時才可以檢測的錯誤 |
logic_error的子類:
異常名稱 |
描述 |
length_error | 試圖生成一個超出該型別最大長度的物件時,例如vector的resize操作 |
domain_error | 引數的值域錯誤,主要用在數學函式中。例如使用一個負值呼叫只能操作非負數的函式 |
out_of_range | 超出有效範圍 |
invalid_argument | 引數不合適。在標準庫中,當利用string物件構造bitset時,而string中的字元不是’0’或’1’的時候,丟擲該異常 |
runtime_error的子類:
異常名稱 |
描述 |
range_error | 計算結果超出了有意義的值域範圍 |
overflow_error | 算術計算上溢 |
underflow_error |
算術計算下溢 |
例:logic_error下的
domain_error:定義域由引數的可能取值組成
invalid_argument:值域由函式可能的返回值組成,指函式傳遞了一個意料之外的值
length_error:指沒有足夠的空間來執行所需的操作,如string類的append()方法合併得到的字串長度超過最大允許長度會引發該異常
out_of_bounds:通常指索引錯誤,如定義一個數組,其operator[]在使用索引無效時會引發該異常
一般而言:
logic_error系列異常表明存在可以通過程式設計修復的問題。
runtime_error系列異常表明存在無法避免的問題。
2,對於bad_alloc 異常與new
對於使用new導致的記憶體分配問題,C++的最新處理方式是讓new引發bad_alloc異常。
標頭檔案new包含bad_alloc類的宣告,它從exception公有派生來。
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
struct Big
{
double stuff[20000];
};
int main()
{
Big* pb;
try
{
cout << "Trying to get a big block of memory:\n";
pb = new Big[11000];
}
catch(bad_alloc& ba)
{
cout << "Caught the exception!\n";
cout << ba.what() << endl;
exit(EXIT_FAILURE);
}
cout << "Memory successfully allocated\n";
pb[0].stuff[0] = 4;
cout << pb[0].stuff[0] << endl;
delete [] pb;
return 0;
}
輸出:
Trying to get a big block of memory:
Caught the exception!
bad allocation
這裡,方法what()返回的字串“std::bad_alloc".
3, 空指標與new
例:int* pi = new (std::nothrow) int;
int* pa = new (std::nothrow) int[500];
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
struct Big
{
double stuff[20000];
};
int main()
{
Big* pb;
pb = new (std::nothrow) Big[11000];
if (pb == 0)
{
cout << "Could not allocate memory.Bye!\n";
exit(EXIT_FAILURE);
}
cout << "Memory successfully allocated\n";
pb[0].stuff[0] = 4;
cout << pb[0].stuff[0] << endl;
delete [] pb;
return 0;
}
輸出:
Could not allocate memory.Bye!