最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11中異常處理機制詳解

 更新時間:2022年09月28日 10:58:14   作者:賣寂寞的小男孩  
傳統(tǒng)的C語言處理異常的方式有兩種:終止程序和返回錯誤碼。在實際中的C語言程序基本都是通過返回錯誤碼的方式來處理錯誤的,部分情況下使用終止程序來處理比較嚴(yán)重的錯誤。本文將通過示例和大家聊聊C++11中異常處理機制,需要的可以參考一下

一、異常的引入

傳統(tǒng)的C語言處理異常的方式有兩種:

1.終止程序:使用assert斷言語句,如果發(fā)生內(nèi)存錯誤等,比如內(nèi)存泄漏或者除0錯誤,都會直接終止程序。

2.返回錯誤碼:通過錯誤碼判斷發(fā)生的異常的類型是什么,如系統(tǒng)的很多庫的接口程序通過把錯誤碼放到errno中,表示錯誤。

在實際中的C語言程序基本都是通過返回錯誤碼的方式來處理錯誤的,部分情況下使用終止程序來處理比較嚴(yán)重的錯誤。

二、C++異常的關(guān)鍵字

目前市面上的大部分的主流語言都是使用異常機制來處理錯誤的,當(dāng)一個函數(shù)發(fā)現(xiàn)自己無法處理一些錯誤的時候會進行拋異常處理,讓函數(shù)直接跳轉(zhuǎn)到捕獲異常的地方去處理異常。

下面介紹C++處理異常的幾個關(guān)鍵字:

throw:當(dāng)問題出現(xiàn)的時候,程序會拋出一個異常,這是通過throw關(guān)鍵字來完成的。

catch:通過異常處捕獲異常,catch塊主要用于處理異常,或者執(zhí)行一些其他的操作。

try:try塊中的代碼標(biāo)識將被激活的特定異常,它的后面一般會跟一個catch塊。

三、異常的拋出與處理規(guī)則

double Disvision(int a, int b)
{
    if (b == 0)
    {
        throw  "Disvision by zero condition";
    }
    else
    {
        return ((double)a / (double)b);
    }
}
void Func()
{
    int len, time;
    cin >> len >> time;
    cout << Disvision(len, time) << endl;
}
int main()
{
    try 
    {
        Func();
    }
    catch(const char* errmsg)
    {
        cout << errmsg << endl;
    }
    catch (...)
    {
        cout << "unkown exception" << endl;
    }
    return 0;
}

當(dāng)向time傳入的值為0的時候,調(diào)用throw拋出異常,catch會捕獲到該異常進行處理。

1.異常是通過拋出對象而引發(fā)的,該對象的類型決定了應(yīng)該激活哪一個catch的處理代碼。

2.被選中的處理代碼是調(diào)用鏈中與該對象類型匹配且離拋出異常位置最近的一個。

在這段程序中,有一個調(diào)用鏈:main()->Func()->Disvision(),在Disvision中拋出異常就會沿著調(diào)用鏈尋找能捕獲異常的catch來執(zhí)行。假設(shè)Func()中有一個與main()中一模一樣的catch函數(shù),那么除0的異常就會優(yōu)先調(diào)用Func()中的catch,因為它離著最近。

3.catch的異常其實是拋出對象的拷貝,因為真正拋出的對象在出作用域的時候就已經(jīng)被銷毀了,拷貝的對象在catch成功之后也會自動銷毀。

4.catch(…)可以捕獲任意類型的異常,但問題是不知道異常錯誤是什么。

5.實際中拋出和捕獲的匹配原則有一個例外,并不都是類型完全匹配,可以拋出的派生類對象,使用基類捕獲。(要引入多態(tài))

6.當(dāng)catch異常之后,會沿著catch后的子句繼續(xù)執(zhí)行,類似goto,算是異常的一個缺陷。

四、異常缺陷的處理

double Disvision(int a, int b)
{
    if (b == 0)
    {
        throw  "Disvision by zero condition";
    }
    else
    {
        return ((double)a / (double)b);
    }
}
void Func()
{
    int* array = new int[10];
    int len, time;
    cin >> len >> time;
    cout << Disvision(len, time) << endl;
    delete[] array;//一旦拋出異常,這里就不會被執(zhí)行
}
int main()
{
    try 
    {
        Func();
    }
    catch(const char* errmsg)
    {
        cout << errmsg << endl;
    }
    catch (...)
    {
        cout << "unkown exception" << endl;
    }
    return 0;
}

對于這段代碼而言,一旦Division拋出異常就會立刻執(zhí)行主函數(shù)中的catch,delete釋放內(nèi)存就不會被執(zhí)行。因此我們需要對這種情況進行處理,即在Func中也捕獲一次異常,但是不對異常進行處理,只是釋放空間:

void Func()
{
    int* array = new int[10];
    int len, time;
    cin >> len >> time;
    try {
        cout << Disvision(len, time) << endl;
    }
    catch (const char* errmsg)
    {
        cout << "釋放空間" << endl;
        delete[] array;
        throw;
    }
}

在釋放空間之后,直接調(diào)用throw表示將捕獲到的異常再拋出去。

五、自定義異常體系

class Exception
{
public:
	Exception(const string& errmsg, int id)
		:_errmsg(errmsg)
		, _id(id)
	{}

	virtual string what() const
	{
		return _errmsg;
	}
protected:
	string _errmsg;
	int _id;
};

class SqlException : public Exception
{
public:
	SqlException(const string& errmsg, int id, const string& sql)
		:Exception(errmsg, id)
		, _sql(sql)
	{}

	virtual string what() const
	{
		string str = "SqlException:";
		str += _errmsg;
		str += "->";
		str += _sql;
		return str;
	}

private:
	const string _sql;
};

class CacheException : public Exception
{
public:
	CacheException(const string& errmsg, int id)
		:Exception(errmsg, id)
	{}

	virtual string what() const
	{
		string str = "CacheException:";
		str += _errmsg;
		return str;
	}
};

class HttpServerException : public Exception
{
public:
	HttpServerException(const string& errmsg, int id, const string& type)
		:Exception(errmsg, id)
		, _type(type)
	{}

	virtual string what() const
	{
		string str = "HttpServerException:";
		str += _type;
		str += ":";
		str += _errmsg;
		return str;
	}

private:
	const string _type;
};

void SQLMgr()
{
	srand(time(0));
	if (rand() % 7 == 0)
	{
		throw SqlException("權(quán)限不足", 100, "select * from name = '張三'");
	}

	//throw "xxxxxx";
}

void CacheMgr()
{
	srand(time(0));
	if (rand() % 5 == 0)
	{
		throw CacheException("權(quán)限不足", 100);
	}
	else if (rand() % 6 == 0)
	{
		throw CacheException("數(shù)據(jù)不存在", 101);
	}

	SQLMgr();
}

void HttpServer()
{
	// ...
	srand(time(0));
	if (rand() % 3 == 0)
	{
		throw HttpServerException("請求資源不存在", 100, "get");
	}
	else if (rand() % 4 == 0)
	{
		throw HttpServerException("權(quán)限不足", 101, "post");
	}
	CacheMgr();
}

void ServerStart()
{
	while (1)
	{
		this_thread::sleep_for(chrono::seconds(1));//休眠1s
		try {
			HttpServer();
		}
		catch (const Exception& e) // 這里捕獲父類對象就可以
		{
			// 多態(tài)
			cout << e.what() << endl;
		}
		catch (...)
		{
			cout << "Unkown Exception" << endl;
		}
	}
}
int main()
{
	ServerStart();
	return 0;
}

這里使用隨機數(shù)進行模擬異常的拋出類型,我們使用父類捕獲異常,拋出子類異常,使用多態(tài)調(diào)用子類中的what()函數(shù)。

六、異常規(guī)范

1.異常規(guī)格說明的目的是為了讓函數(shù)使用者知道。可以在函數(shù)的后面接throw類(類型),列出這個函數(shù)可能拋的所有異常類型。

2.函數(shù)后面接throw(),表示函數(shù)不拋異常。

3.若無異常接口聲明,則此函數(shù)可以拋擲任何類型的異常。

void func() throw(A, B, C, D);//只會拋A/B/C/D中的某種類型的異常
void* operator new(size_t size) throw(bad alloc);//這里表示這個函數(shù)只會拋出bad_alloc的異常
void* operator new(size_t size, void* ptr) throw();//這個函數(shù)不會拋異常

在C++11中,引入了noexception

bool Compare(int x, int y) noexcept(noexcept(x > y))  //C++11
{
    return x > y;//表示如果x > y不發(fā)生異常,則Compare函數(shù)不會發(fā)生異常。
}

七、異常安全

構(gòu)造函數(shù)完成對象的初始化,最好不要在構(gòu)造函數(shù)中拋異常,否則可能導(dǎo)致對象不完整,或沒有完全初始化。

析構(gòu)函數(shù)主要完成資源的清理,最好不要在析構(gòu)函數(shù)中拋異常,否則可能導(dǎo)致資源泄漏(內(nèi)存泄漏,句柄未關(guān)閉)。

C++異常經(jīng)常會導(dǎo)致資源泄漏的問題,比如在new和delete中拋出了異常,導(dǎo)致內(nèi)存泄漏,在lock和unlock之間拋出了異常導(dǎo)致死鎖,C++經(jīng)常使用RAII來解決以上問題,關(guān)于RAII我們在智能指針中講解。

八、異常的優(yōu)缺點

1.優(yōu)點

1.相比錯誤碼,更加清晰展示出錯信息。

2.很多庫中包含異常,boost,gtest,gmock等常用的庫,使用它們也需要異常。

3.部分函數(shù)使用異常更好處理,比如構(gòu)造函數(shù)沒有返回值,不方便使用錯誤碼方式處理,比如T&operator這樣的函數(shù),只有一個返回值,如果pos越界了只能使用異?;蛘呓K止程序處理,沒辦法通過返回值表示錯誤。

2.缺點

1.異常類似goto,會導(dǎo)致程序的執(zhí)行流亂跳,并且非?;靵y。

2.C++沒有垃圾回收機制,可能導(dǎo)致內(nèi)存泄漏。

3.各個公司的異常體系不同,有一定的學(xué)習(xí)成本。

到此這篇關(guān)于C++11中異常處理機制詳解的文章就介紹到這了,更多相關(guān)C++11異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言中的運算符和結(jié)合性問題

    C語言中的運算符和結(jié)合性問題

    這篇文章主要介紹了C語言中的運算符和結(jié)合性問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • C++中stack、queue、vector的用法詳解

    C++中stack、queue、vector的用法詳解

    本文通過實例代碼給大家介紹了C++中stack、queue、vector的用法,需要的朋友參考下吧
    2017-08-08
  • C++中的頭文件與Extern(外部函數(shù)調(diào)用)方式

    C++中的頭文件與Extern(外部函數(shù)調(diào)用)方式

    這篇文章主要介紹了C++中的頭文件與Extern(外部函數(shù)調(diào)用)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C語言預(yù)處理器使用方法講解

    C語言預(yù)處理器使用方法講解

    C預(yù)處理器不是編譯器的組成部分,但是它是編譯過程中一個單獨的步驟。簡言之,C預(yù)處理器只不過是一個文本替換工具而已,它們會指示編譯器在實際編譯之前完成所需的預(yù)處理。我們將把C預(yù)處理器(C Preprocessor)簡寫為CPP
    2022-12-12
  • C語言與java語言中關(guān)于二維數(shù)組的區(qū)別

    C語言與java語言中關(guān)于二維數(shù)組的區(qū)別

    這篇文章主要介紹了C語言與java語言中關(guān)于二維數(shù)組的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • C++11模板元編程-std::enable_if示例詳解

    C++11模板元編程-std::enable_if示例詳解

    這篇文章主要給大家介紹了關(guān)于C++11模板元編程-std::enable_if的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • C++內(nèi)存管理面經(jīng)

    C++內(nèi)存管理面經(jīng)

    這篇文章主要介紹了C++的內(nèi)存分配方式以及介紹了下棧和堆的區(qū)別,感興趣的小伙伴可以參考閱讀本文
    2023-03-03
  • 漫畫講解C語言中最近公共祖先的三種類型

    漫畫講解C語言中最近公共祖先的三種類型

    這篇文章主要總結(jié)了使用C語言查找最近公共祖先的三種方法類型,用漫畫的方式講解原理定義,看上去更生動形象,幫助你更好的理解透徹,快來跟著本文往下看吧
    2021-11-11
  • 使用?Visual?Studio?2022?開發(fā)?Linux?C++?應(yīng)用程序的過程詳解

    使用?Visual?Studio?2022?開發(fā)?Linux?C++?應(yīng)用程序的過程詳解

    Visual?Studio?2022?引入了用于?Linux?C++?開發(fā)的本機?WSL2?工具集,可以構(gòu)建和調(diào)試?Linux?C++?代碼,并提供了非常好的?Linux?文件系統(tǒng)性能、GUI?支持和完整的系統(tǒng)調(diào)用兼容性,這篇文章主要介紹了使用Visual?Studio?2022?開發(fā)?Linux?C++?應(yīng)用程序,需要的朋友可以參考下
    2021-11-11
  • 淺談stringstream 的.str()正確用法和清空操作

    淺談stringstream 的.str()正確用法和清空操作

    下面小編就為大家?guī)硪黄獪\談stringstream 的.str()正確用法和清空操作。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12

最新評論

玉门市| 灵台县| 綦江县| 涿鹿县| 板桥市| 大竹县| 东乡族自治县| 东城区| 开封市| 宁阳县| 临城县| 集安市| 离岛区| 报价| 西畴县| 武陟县| 安达市| 龙山县| 西平县| 山西省| 吉木乃县| 阜阳市| 科尔| 苏州市| 惠东县| 平乡县| 广汉市| 河北区| 五家渠市| 中牟县| 水城县| 包头市| 平乐县| 乌拉特后旗| 新安县| 通州市| 夏邑县| 阳江市| 嘉善县| 旅游| 定日县|