溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++Primer_筆記_異常處理

發(fā)布時間:2020-07-23 09:10:42 來源:網(wǎng)絡(luò) 閱讀:370 作者:xujiafan_2015 欄目:編程語言

    異常,當(dāng)一個函數(shù)發(fā)現(xiàn)一個無法處理的錯誤時拋出異常,讓函數(shù)的

調(diào)用者直接或間接的處理這個問題。 

    異常處理,是一種允許兩個獨立開發(fā)的程序組件在程序執(zhí)行期間遇到程序不正常的

情況(稱為異常,exception )時相互通信的機(jī)制。

異常拋出:

throw (表達(dá)式)

異常發(fā)現(xiàn)與拋出異常:

/*發(fā)現(xiàn)異常并且拋出異常*/
try
{
    //可能出現(xiàn)異常的語句
}

捕獲異常:

catch(類型名 + 形參名)    //捕獲特定類型異常
{
    
}
catch(...)           //捕獲任意類型異常(在不確定異常類型時使用) 
{

}

下來看一個簡單的例子:

#include<iostream>
using namespace std;

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

int main()
{
    Div(1,0);
    system("pause");
    return 0;
}

結(jié)果顯示:

C++Primer_筆記_異常處理

程序直接崩潰,由于調(diào)用時傳入第二個參數(shù)是零,零不能作除數(shù),所以會崩潰,下面使用異常處理這個問題:

#include <iostream>
#include  <string>
using namespace std;

int Div(int a, int b)
{
    if(b == 0)
    {
	throw string("parameter error.");//異常拋出
    }
    return a/b;
}
int main()
{
    try
    {
    Div(1, 0);//發(fā)現(xiàn)異常,與拋出異常
    }
    catch(const string& S)
    {
    	cout<<S<<endl;//捕獲異常
    }
    system("pause");
    return 0;
}

C++Primer_筆記_異常處理

程序可以正常運行,也可以看到異常出現(xiàn)的地方,這樣就可以很清楚的解決這個問題。

下面再看個了例子:

#include <iostream>
#include <string>
using namespace std;

void test()
{
    int* p = new int(1);
    if(1)
    {
	throw string("error.");
    }
    delete p;	
}

int main()
{
    try
    {
	test();
    }
    catch(const string& S)
    {
	cout<<S<<endl;
    }
    system("pause");
    return 0;
}

結(jié)果顯示:

C++Primer_筆記_異常處理

這個程序運行貌似沒有問題,其實問題大了。

void test()
{
    int* p = new int(1);
    if(1)
    {
	throw string("error.");
	//程序執(zhí)行到這里,直接就去catch()那塊了,
	//導(dǎo)致new出來的內(nèi)存沒有釋放,造成內(nèi)存泄漏。
    }
    delete p;	
}

內(nèi)存泄漏:

        會導(dǎo)致你開辟出來的那塊內(nèi)存以后就不可以用了,這樣多泄漏幾次,你的電腦就哈哈了,會很卡,很卡。

內(nèi)存泄漏危害:

        從用戶使用程序的角度來看,內(nèi)存泄漏本身不會產(chǎn)生什么危害,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在。真正有危害的是內(nèi)存泄漏的堆積,這會最終消耗盡系統(tǒng)所有的內(nèi)存。從這個角度來說,一次性內(nèi)存泄漏并沒有什么危害,因為它不會堆積,而隱式內(nèi)存泄漏危害性則非常大,因為較之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到。

當(dāng)然,這里并不是說內(nèi)存泄漏,下面可以用異常來處理上面這個問題:

#include <iostream>
#include <string>
using namespace std;

void test()
{
	int* p = new int(1);
	try//發(fā)現(xiàn)異常
	{
		if(1)
		{
			throw string("error.");//異常拋出
		}
	}
	catch(...)//捕獲異常
	{
		delete p;//釋放開辟的空間
		throw;//異常重新拋出
	}
	delete p;	
}

int main()
{
	try//發(fā)現(xiàn)重新拋出的異常
	{
		test();
	}
	catch(const string& S)//捕獲異常
	{
		cout<<S<<endl;
	}
	system("pause");
	return 0;
}

結(jié)果顯示:

C++Primer_筆記_異常處理

這樣就不會出現(xiàn)內(nèi)存泄漏,也會很清楚的在控制臺顯示錯誤的信息。

異常重新拋出:在異常處理過程中也可能存在單個catch 子句不能完全處理異常的情況。在某些修

正動作之后,catch 子句可能決定該異常必須由函數(shù)調(diào)用鏈中更上級的函數(shù)來處理那么catch子句可以通過重新拋出(rethrow )該異常把異常傳遞給函數(shù)調(diào)用鏈中更上級的另一個catch子句,rethrow 表達(dá)式的形式為:

throw;

rethrow 表達(dá)式重新拋出該異常對象rethrow 只能出現(xiàn)在catch 子句的復(fù)合語句中。被重新拋出的對象就是其原來的異常對象。


棧展開:

    在查找用來處理被拋出異常的catch 子句時因為異常而退出復(fù)合語句和函數(shù)定義這個過

        拋出異常的時候,將暫停當(dāng)前函數(shù)的執(zhí)行,開始查找對應(yīng)的匹配catch語句。首先檢查throw本身是否在catch塊內(nèi)部,如果是,再查找匹配的catch語句。如果有匹配的,則處理。沒有則退出當(dāng)前函數(shù)棧,繼續(xù)在調(diào)用函數(shù)的棧中進(jìn)行查找。不斷重復(fù)上述過程。若到達(dá)main函數(shù)的棧,依舊沒有匹配的,則終止程序。

        上述這個沿著調(diào)用鏈查找匹配的catch語句的過程稱為棧展開。找到匹配的catch語句并處理以后,會繼續(xù)沿著catch語句后繼繼續(xù)執(zhí)行。


異常捕獲的匹配規(guī)則:

    異常對象的類型與catch說明符的類型必須完全匹配。

    只有以下幾種情況例外:

        1. 允許從非const對象到const的轉(zhuǎn)換。

        2. 允許從派生類型到基類類型的轉(zhuǎn)換。

        3. 將數(shù)組轉(zhuǎn)換為指向數(shù)組類型的指針,將函數(shù)轉(zhuǎn)換為指向函數(shù)類型的指針。

異常處理總結(jié):

        異常處理就是通過throw,try,catch,這三個關(guān)鍵字,來發(fā)現(xiàn)異常,并拋出異常,捕獲異常,可以做出相應(yīng)的處理。(這只是簡單的異常處理)

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI