1. 程式人生 > >C++ 異常處理(三) exception類

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!