程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++中的異常 exception

c++中的異常 exception

編輯:C++入門知識

c++中的異常 exception


變成入門的時候可能經常遇到的錯誤:

 

this application has requested the runtime to terminate it in an unusual way. Please contact the application's support team for more information
這是由於程序在運行時發生了未知的錯誤,例如:打開不存在的文件,爆棧,除數為0等錯誤,程序直接調用abort()函數直接終止程序的運行;當然,顯示的信息不一定就是上面這一條

 

 

上面這個情況是程序自己解決異常的問題,這種方式實際上是非常粗暴的,直接終止了程序運行,而且你還不知道程序錯在哪個位置,是因為什麼錯(當然,用萬能的cout強行追蹤也是闊以滴,哈哈)

所幸,c++引入了比較優雅的try... catch....異常機制來讓程序猿自己處理可能出現的異常,這種機制實際上是避免了程序直接調用abort()函數,使程序看起來更優雅一點,具體結構如下:

 

try{
// 可能會引發異常的代碼塊
}catch(exception argument){
//處理捕捉到的異常
}
try...catch...機制實際上主要是以下幾個部分:

 

1.將可能引發異常的代碼(如:文件讀取等)放入try塊中

2.判斷在什麼時候拋出異常,也就是可能引發異常的代碼塊中需要添加異常拋出的語句,拋出異常通常使用 throw關鍵字

3.catch首先通過異常參數列表匹配產生的異常,如果匹配成功,那麼執行catch塊的代碼

先寫一個簡單的例子

首先是沒有異常處理的

 

#include 
using namespace std;

int division(int a, int b){
	return a / b;
}

int main(){
	int a, b;
	while(1){
		cout << Please input a and b: ;
		cin >> a >> b;
		cout << a / b =  << division(a, b) << endl;
	}
	return 0;
}
隨便測試了一下,結果如下:

 

\

可以看到程序是直接結束了,並沒有理會那個while(1)

那我們現在來加一下異常

 

#include 
using namespace std;


int division(int a, int b){
	if(b == 0)
		throw Divisor is not allowed to be 0;
	return a / b;
}


int main(){
	int a, b;
	while(1){
		cout << Please input a and b: ;
		cin >> a >> b;
		try{
			cout << a / b =  << division(a, b) << endl;
			cout << successful division << endl;
		}catch(const char* msg){
			cout << Error message is:  << msg << endl; 
		}
		
	}
	return 0;
}
運行結果:

 

\

可以看到現在我們可以知道是哪個地方除了問題,並且可以print出異常信息,更重要的是,程序依然可以繼續往下執行

可以看到,在產生異常之後,程序馬上跳轉到匹配的catch塊執行,而終止try塊中代碼的執行

當然,如果沒有匹配上產生的異常(上面這個例子只是簡單的匹配字符串,實際上更常用的是異常對象匹配),那麼程序同樣會調用abort()函數,然後編譯器給你提示一堆錯誤的信息時候,你的程序就掛掉了

看了上面這個例子,是不是感覺try和catch有一點實參和型參的感覺

那下面我們來看一個例子

我們現在吧異常當作一個MyException的對象來處理:

 

#include 
using namespace std;

class MyException{
public:
	MyException(){
		msg = ;
		cout << in the default constructor << endl;
	}
	MyException(MyException &aa){
		msg = aa.msg;
		cout << in the copy constructor << endl;
	}
	MyException(string msg_){
		msg = msg_;
		cout << in the string constructor << endl;
	}
	string what(){
		return msg;
	}
	string msg;
};

int division(int a, int b){
	if(b == 0){
		MyException me(Divisor is not allowed to be 0);
		throw me;
	}
		
	return a / b;
}

int main(){
	int a, b;
	while(1){
		cout << Please input a and b: ;
		cin >> a >> b;
		try{
			cout << a / b =  << division(a, b) << endl;
			cout << successful division << endl;
		}catch(MyException &ME){
			cout << Error message is:  << ME.what() << endl; 
		}
		
	}
	return 0;
}
運行結果如下:

 

\

這裡大家可能會疑惑,因為在正常的函數參數傳遞中,我們傳遞引用就是為了避免重復地構造對象,但是在try...catch...中就不一樣了,throw在拋出異常的時候,無論catch是接受引用傳遞還是接受值傳遞,編譯器都會在throw異常時新建一個臨時對象,所以才會有上面結果中顯示的兩次構造MyException對象,而catch中的引用不過是指向這個臨時對象而不是原本的那個MyException對象,一搬都是吧拋出異常跟新建異常對象合並在一起,這樣更簡潔,所以上面拋出異常可以寫成

 

throw MyException(Divisor is not allowed to be 0);
本來還想說一下exception和他的一些派生類的,不過好像網上挺多這些東西的,也沒什麼可講的,就收工了吧

 

 


 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved