日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++异常Try catch

發布時間:2024/4/11 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++异常Try catch 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
c++異常Try catch
分類:?c++專區?功能函數測試集錦?1505人閱讀?評論(0)?收藏?舉報

一、簡單的例子
首先通過一個簡單的例子來熟悉C++ 的 try/catch/throw:

1 #include<iostream.h> //包含頭文件 2 #include<stdlib.h> 3 double fuc(double x, double y) //定義函數 4 { 5 if(y==0) 6 { 7 throw y; //除數為0,拋出異常 8 } 9 return x/y; //否則返回兩個數的商 10 } 11 void main() 12 { 13 double res; 14 try //定義異常 15 { 16 res=fuc(2,3); 17 cout<<"The result of x/y is : "<<res<<endl; 18 res=fuc(4,0); //出現異常 19 } 20 catch(double) //捕獲并處理異常 21 { 22 cerr<<"error of dividing zero.\n"; 23 exit(1); //異常退出程序 24 } 25 }

catch 的數據類型需要與throw出來的數據類型相匹配的。
?
二、catch(...)的作用
catch(…)能夠捕獲多種數據類型的異常對象,所以它提供給程序員一種對異常對象更好的控制手段,使開發的軟件系統有很好的可靠性。因

此一個比較有經驗的程序員通常會這樣組織編寫它的代碼模塊,如下:
void Func()
{
try
{
??? // 這里的程序代碼完成真正復雜的計算工作,這些代碼在執行過程中
??? // 有可能拋出DataType1、DataType2和DataType3類型的異常對象。
}
catch(DataType1& d1)
{
}
catch(DataType2& d2)
{
}
catch(DataType3& d3)
{
}
// 注意上面try block中可能拋出的DataType1、DataType2和DataType3三
// 種類型的異常對象在前面都已經有對應的catch block來處理。但為什么
// 還要在最后再定義一個catch(…) block呢?這就是為了有更好的安全性和
// 可靠性,避免上面的try block拋出了其它未考慮到的異常對象時導致的程
// 序出現意外崩潰的嚴重后果,而且這在用VC開發的系統上更特別有效,因
// 為catch(…)能捕獲系統出現的異常,而系統異常往往令程序員頭痛了,現
// 在系統一般都比較復雜,而且由很多人共同開發,一不小心就會導致一個
// 指針變量指向了其它非法區域,結果意外災難不幸發生了。catch(…)為這種
// 潛在的隱患提供了一種有效的補救措施。
catch(…)
{
}
}
三、異常中采用面向對象的處理
首先看下面的例子:
void OpenFile(string f)
{
try
{
?? // 打開文件的操作,可能拋出FileOpenException
}
catch(FileOpenException& fe)
{
?? // 處理這個異常,如果這個異常可以很好的得以恢復,那么處理完畢后函數
?? // 正常返回;否則必須重新拋出這個異常,以供上層的調用函數來能再次處
?? // 理這個異常對象
?? int result = ReOpenFile(f);
?? if (result == false) throw;
}
}

void ReadFile(File f)
{
try
{
?? // 從文件中讀數據,可能拋出FileReadException
}
catch(FileReadException& fe)
{
?? // 處理這個異常,如果這個異常可以很好的得以恢復,那么處理完畢后函數
?? // 正常返回;否則必須重新拋出這個異常,以供上層的調用函數來能再次處
?? // 理這個異常對象
?? int result = ReReadFile(f);
?? if (result == false) throw;
}
}

void WriteFile(File f)
{
try
{
??? // 往文件中寫數據,可能拋出FileWriteException
}
catch(FileWriteException& fe)
{
??? // 處理這個異常,如果這個異常可以很好的得以恢復,那么處理完畢后函數
??? // 正常返回;否則必須重新拋出這個異常,以供上層的調用函數來能再次處理這個異常對象
??? int result = ReWriteFile(f);
??? if (result == false) throw;?
}?
}

void Func()
{
try
{
?? // 對文件進行操作,可能出現FileWriteException、FileWriteException
?? // 和FileWriteException異常
?? OpenFile(…);
?? ReadFile(…);
?? WriteFile(…);
}
// 注意:FileException是FileOpenException、FileReadException和FileWriteException
// 的基類,因此這里定義的catch(FileException& fe)能捕獲所有與文件操作失敗的異
// 常。
catch(FileException& fe)
{
?? ExceptionInfo* ef = fe.GetExceptionInfo();
?? cout << “操作文件時出現了不可恢復的錯誤,原因是:”<< fe << endl;
}
}

下面是更多面向對象和異常處理結合的例子:
#include <iostream.h>
class ExceptionClass
{
??? char* name;
public:
??? ExceptionClass(const char* name="default name")?
??? {
???????????? cout<<"Construct "<<name<<endl;
???????????? this->name=name;
??? }
?? ~ExceptionClass()
??? {
???????????? cout<<"Destruct "<<name<<endl;
??? }
??? void mythrow()
?? {
??????????? throw ExceptionClass("my throw");
?? }
}

void main()
{
?????? ExceptionClass e("Test");
?????? try
?????? {
?????????? e.mythrow();
?????? }??
?????? catch(...)
????? {
???????? cout<<”*********”<<endl;
?????? }
}
這是輸出信息:
Construct Test
Construct my throw
Destruct my throw
****************
Destruct my throw?? (這里是異常處理空間中對異常類的拷貝的析構)
Destruct Test
======================================
不過一般來說我們可能更習慣于把會產生異常的語句和要throw的異常類分成不同的類來寫,下面的代碼可以是我們更愿意書寫的:
class ExceptionClass
{
public:
??? ExceptionClass(const char* name="Exception Default Class")
?? {
?????? cout<<"Exception Class Construct String"<<endl;
?? }
?? ~ExceptionClass()
?? {
????? cout<<"Exception Class Destruct String"<<endl;
?? }
?? void ReportError()
?? {
????? cout<<"Exception Class:: This is Report Error Message"<<endl;
?? }
};

class ArguClass
{
?? char* name;
public:
?? ArguClass(char* name="default name")
?? {
????? cout<<"Construct String::"<<name<<endl;
????? this->name=name;
?? }
?? ~ArguClass()
?? {
????? cout<<"Destruct String::"<<name<<endl;
?? }
?? void mythrow()
?? {
????? throw ExceptionClass("my throw");
?? }??????
};

_tmain()
{
?? ArguClass e("haha");
?? try
?? {
???? e.mythrow();
?? }
?? catch(int)
?? {
???? cout<<"If This is Message display screen, This is a Error!!"<<endl;? //這行不會執行
?? }
?? catch(ExceptionClass pTest)
?? {
????? pTest.ReportError();
?? }
?? catch(...)
? {
?????? cout<<"***************"<<endl;??
? }
}
輸出Message:
Construct String::haha
Exception Class Construct String
Exception Class Destruct String
Exception Class:: This is Report Error Message
Exception Class Destruct String
Destruct String::haha

四、構造和析構中的異常拋出
先看個程序,假如我在構造函數的地方拋出異常,這個類的析構會被調用嗎?可如果不調用,那類里的東西豈不是不能被釋放了?

#include <iostream.h>
#include <stdlib.h>

class ExceptionClass1
{
?????? char* s;
public:
?????? ExceptionClass1()
????? {
????????????? cout<<"ExceptionClass1()"<<endl;
????????????? s=new char[4];
????????????? cout<<"throw a exception"<<endl;
????????????? throw 18;
?????? }
?????? ~ExceptionClass1()
????? {
????????????? cout<<"~ExceptionClass1()"<<endl;
????????????? delete[] s;
?????? }
};

void main()
{
?????? try
?????? {
???????????? ExceptionClass1 e;
?????? }
?????? catch(...)
?????? {}
}

結果為:

ExceptionClass1()
throw a exception

在這兩句輸出之間,我們已經給S分配了內存,但內存沒有被釋放(因為它是在析構函數中釋放的)。應該說這符合實際現象,因為對象沒有

完整構造。

為了避免這種情況,我想你也許會說:應避免對象通過本身的構造函數涉及到異常拋出。即:既不在構造函數中出現異常拋出,也不應在構

造函數調用的一切東西中出現異常拋出。
但是在C++中可以在構造函數中拋出異常,經典的解決方案是使用STL的標準類auto_ptr。

那么,在析構函數中的情況呢?我們已經知道,異常拋出之后,就要調用本身的析構函數,如果這析構函數中還有異常拋出的話,則已存在

的異常尚未被捕獲,會導致異常捕捉不到。

五、標準C++異常類
標準異常都派生自一個公共的基類exception。基類包含必要的多態性函數提供異常描述,可以被重載。下面是exception類的原型:
class exception
{
public:
??? exception() throw();
??? exception(const exception& rhs) throw();
??? exception& operator=(const exception& rhs) throw();
??? virtual ~exception() throw();
??? virtual const char *what() const throw();
};
?
C++有很多的標準異常類:
namespace std
{
??? //exception派生
??? class logic_error; //邏輯錯誤,在程序運行前可以檢測出來
?
??? //logic_error派生
??? class domain_error; //違反了前置條件
??? class invalid_argument; //指出函數的一個無效參數
??? class length_error; //指出有一個超過類型size_t的最大可表現值長度的對象的企圖
??? class out_of_range; //參數越界
??? class bad_cast; //在運行時類型識別中有一個無效的dynamic_cast表達式
??? class bad_typeid; //報告在表達試typeid(*p)中有一個空指針p
???
??? //exception派生
??? class runtime_error; //運行時錯誤,僅在程序運行中檢測到
???
??? //runtime_error派生
??? class range_error; //違反后置條件
??? class overflow_error; //報告一個算術溢出
??? class bad_alloc; //存儲分配錯誤
}
標準庫異常類定義在以下四個頭文件中
??? 1、exception頭文件:定義了最常見的標準異常類,其類名為exception。只通知異常的產生,但不會提供更多的信息
??? 2、stdexcept頭文件定義了以下幾種常見異常類
?? 函數?????????????????????????????????????????????? 功能或作用
exception???????????????????????????????????????????? 最常見的問題
runtime_error???????????????????????????????????????? 運行時錯誤:僅在運行時才能檢測到的問題
range_error????????????????????????????????????????? 運行時錯誤:生成的結果超出了有意義的值域范圍
overflow_error??????????????????????????????????????? 運行時錯誤:計算上溢
underflow_error?????????????????????????????????????? 運行時錯誤:計算下溢
?
logic_error??????????????????????????????????????? 邏輯錯誤:可在運行前檢測到的問題
domain_error?????????????????????????????????????? 邏輯錯誤:參數的結果值不存在
invalid_argument?????????????????????????????????? 邏輯錯誤:不合適的參數
length_error?????????????????????????????????????? 邏輯錯誤:試圖生成一個超出該類型最大長度的對象
out_of_range?????????????????????????????????????? 邏輯錯誤:使用一個超出有效范圍的值
??? 3、new頭文件定義了bad_alloc異常類型,提供因無法分配內存而由new拋出的異常
??? 4、type_info頭文件定義了bad_cast異常類型(要使用type_info必須包含typeinfo頭文件)
??? 下面是使用異常類的例子:
??? 首先,我定義了幾個異常類,這些類也可以從標準異常類進行派生,如下
class BadInitializers
{
public:
?BadInitializers() {}
};
class OutOfBounds
{
public:
?OutOfBounds(int i) { cout<<"Size "<<i<<" is illegal!!!"<<endl; }
};
class SizeMismatch
{
public:
?SizeMismatch() {}
};
?
然后要在程序中需要的地方使用throw來拋出異常類,兩個拋出異常類的例子如下
template <class T>
Array1D<T>::Array1D(int sz)
{
? if(sz<0)
? {
??? //throw BadInitializers();
??? throw invalid_argument("Size has to be bigger than 0!!!");

? }
?size=sz;
?element=new T[size];
}
template <class T>
T &Array1D<T>::operator[](int i) const
{
?if(i<0||i>=size)
?{
??? throw OutOfBounds(i);
?}
?return element[i];
}
?
然后在主程序中使用try...catch...來捕獲異常,并進行相應的處理,如下
try
{
? int i=0;
? Array1D<int> a1(5);
? a1[0]=1;
? a1[1]=3;
? a1[2]=5;
? a1[3]=7;
? a1[4]=8;
? Array1D<int> a2(a1);
? for(i=0;i<a2.Size();i++)
? {
?? cout<<a2[i]<<" ";
? }
? cout<<endl;
? Array1D<int> a3(5);
? a3=a1+a2;
? cout<<a3;
}
?catch(BadInitializers)
?{
? cout<<"Error:BadInitializers!!!"<<endl;
?}
?catch(OutOfBounds &e)
?{
? cout<<"Error:OutOfBounds!!!"<<endl;
?}
?catch(SizeMismatch &e)
?{
? cout<<"Error:SizeMismatch!!!"<<endl;
?}
?catch(invalid_argument &e)
?{
? cout<<"Error:"<<e.what()<<endl;
?}
?catch(...)
?{
? cout<<"An unknown error!!!"<<endl;
?}
?
六、try finally使用
__try
{
?? file://保護塊
}
__finally
{
? file://結束處理程序
}
在上面的代碼段中,操作系統和編譯程序共同來確保結束處理程序中的__f i n a l l y代碼塊能夠被執行,不管保護體(t r y塊)是如何

退出的。不論你在保護體中使用r e t u r n,還是g o t o,或者是longjump,結束處理程序(f i n a l l y塊)都將被調用。

我們來看一個實列:(返回值:10, 沒有Leak,性能消耗:小)
DWORD Func_SEHTerminateHandle()
{
DWORD dwReturnData = 0;
HANDLE hSem = NULL;
const char* lpSemName = "TermSem";
hSem =? CreateSemaphore(NULL, 1, 1, lpSemName);
__try
{
? WaitForSingleObject(hSem,INFINITE);
? dwReturnData = 5;
}
__finally
{
? ReleaseSemaphore(hSem,1,NULL);
? CloseHandle(hSem);
}
dwReturnData += 5;
return dwReturnData;
}
這段代碼應該只是做為一個基礎函數,我們將在后面修改它,來看看結束處理程序的作用:
====================
在代碼加一句:(返回值:5, 沒有Leak,性能消耗:中下)
DWORD Func_SEHTerminateHandle()
{
DWORD dwReturnData = 0;
HANDLE hSem = NULL;
const char* lpSemName = "TermSem";
hSem =? CreateSemaphore(NULL, 1, 1, lpSemName);
__try
{
? WaitForSingleObject(hSem,INFINITE);
? dwReturnData = 5;
? return dwReturnData;
}
__finally
{
? ReleaseSemaphore(hSem,1,NULL);
? CloseHandle(hSem);
}
dwReturnData += 5;
return dwReturnData;
}
在try塊的末尾增加了一個return語句。這個return語句告訴編譯程序在這里要退出這個函數并返回dwTemp變量的內容,現在這個變量的值是

5。但是,如果這個return語句被執行,該線程將不會釋放信標,其他線程也就不能再獲得對信標的控制。可以想象,這樣的執行次序會產生

很大的問題,那些等待信標的線程可能永遠不會恢復執行。
通過使用結束處理程序,可以避免return語句的過早執行。當return語句試圖退出try塊時,編譯程序要確保finally塊中的代碼首先被執行

。要保證finally塊中的代碼在try塊中的return語句退出之前執行。在程序中,將ReleaseSemaphore的調用放在結束處理程序塊中,保證信

標總會被釋放。這樣就不會造成一個線程一直占有信標,否則將意味著所有其他等待信標的線程永遠不會被分配CPU時間。
在finally塊中的代碼執行之后,函數實際上就返回。任何出現在finally塊之下的代碼將不再執行,因為函數已在try塊中返回。所以這個函

數的返回值是5,而不是10。
讀者可能要問編譯程序是如何保證在try塊可以退出之前執行finally塊的。當編譯程序檢查源代碼時,它看到在try塊中有return語句。這樣

,編譯程序就生成代碼將返回值(本例中是5)保存在一個編譯程序建立的臨時變量中。編譯程序然后再生成代碼來執行f i n a l l y塊中

包含的指令,這稱為局部展開。更特殊的情況是,由于try塊中存在過早退出的代碼,從而產生局部展開,導致系統執行finally塊中的內容

。在finally塊中的指令執行之后,編譯程序臨時變量的值被取出并從函數中返回。
可以看到,要完成這些事情,編譯程序必須生成附加的代碼,系統要執行額外的工作。
?
finally塊的總結性說明
我們已經明確區分了強制執行finally塊的兩種情況:
? 從try塊進入finally塊的正常控制流。
? 局部展開:從try塊的過早退出(goto、long jump、continue、break、return等)強制控制轉移到finally塊。
第三種情況,全局展開( global unwind),這個以后再看。
?
七、C++異常參數傳遞
從語法上看,在函數里聲明參數與在catch子句中聲明參數是一樣的,catch里的參數可以是值類型,引用類型,指針類型。例如:
try
{
?? .....
}
catch(A a)
{
}
catch(B& b)
{
}
catch(C* c)
{
}
? 盡管表面是它們是一樣的,但是編譯器對二者的處理卻又很大的不同。調用函數時,程序的控制權最終還會返回到函數的調用處,但是拋

出一個異常時,控制權永遠不會回到拋出異常的地方。
class A;
void func_throw()
{
???? A a;
???? throw a;? //拋出的是a的拷貝,拷貝到一個臨時對象里
}
try
{
??? func_throw();
}
catch(A a)? //臨時對象的拷貝
{
}
當我們拋出一個異常對象時,拋出的是這個異常對象的拷貝。當異常對象被拷貝時,拷貝操作是由對象的拷貝構造函數完成的。該拷貝構造

函數是對象的靜態類型(static type)所對應類的拷貝構造函數,而不是對象的動態類型(dynamic type)對應類的拷貝構造函數。此時對象會

丟失RTTI信息。
異常是其它對象的拷貝,這個事實影響到你如何在catch塊中再拋出一個異常。比如下面這兩個catch塊,乍一看好像一樣:
catch (A& w) // 捕獲異常
{
 // 處理異常
 throw; // 重新拋出異常,讓它繼續傳遞
}
catch (A& w) // 捕獲Widget異常
{
 // 處理異常
 throw w; // 傳遞被捕獲異常的拷貝
}
? 第一個塊中重新拋出的是當前異常(current exception),無論它是什么類型。(有可能是A的派生類)??
? 第二個catch塊重新拋出的是新異常,失去了原來的類型信息。
? 一般來說,你應該用throw來重新拋出當前的異常,因為這樣不會改變被傳遞出去的異常類型,而且更有效率,因為不用生成一個新拷貝。
看看以下這三種聲明:
catch (A w) ... // 通過傳值
catch (A& w) ... // 通過傳遞引用,一個被異常拋出的對象(總是一個臨時對象)可以通過普通的引用捕獲
catch (const A& w) ... //const引用
? 回到異常對象拷貝上來。我們知道,當用傳值的方式傳遞函數的參數,我們制造了被傳遞對象的一個拷貝,并把這個拷貝存儲到函數的參

數里。同樣我們通過傳值的方式傳遞一個異常時,也是這么做的當我們這樣聲明一個catch子句時:
catch (A w) ... // 通過傳值捕獲
會建立兩個被拋出對象的拷貝,一個是所有異常都必須建立的臨時對象,第二個是把臨時對象拷貝進w中。實際上,編譯器會優化掉一個拷貝

。同樣,當我們通過引用捕獲異常時,
catch (A& w) ... // 通過引用捕獲
catch (const A& w) ... //const引用捕獲
這仍舊會建立一個被拋出對象的拷貝:拷貝是一個臨時對象。相反當我們通過引用傳遞函數參數時,沒有進行對象拷貝。話雖如此,但是不是

所有編譯器都如此。
?
另外,通過指針拋出異常與通過指針傳遞參數是相同的。不論哪種方法都是一個指針的拷貝被傳遞。你不能認為拋出的指針是一個指向局部

對象的指針,因為當異常離開局部變量的生存空間時,該局部變量已經被釋放。Catch子句將獲得一個指向已經不存在的對象的指針。這種行

為在設計時應該予以避免。
另外一個重要的差異是在函數調用者或拋出異常者與被調用者或異常捕獲者之間的類型匹配的過程不同。在函數傳遞參數時,如果參數不匹

配,那么編譯器會嘗試一個類型轉換,如果存在的話。而對于異常處理的話,則完全不是這樣。見一下的例子:

void func_throw()
{
???? CString a;
???? throw a;? //拋出的是a的拷貝,拷貝到一個臨時對象里
}

try
{
func_throw();
}
catch(const char* s)
{
}
拋出的是CString,如果用const char*來捕獲的話,是捕獲不到這個異常的。
盡管如此,在catch子句中進行異常匹配時可以進行兩種類型轉換。第一種是基類與派生類的轉換,一個用來捕獲基類的catch子句也可以處

理派生類類型的異常。反過來,用來捕獲派生類的無法捕獲基類的異常。
第二種是允許從一個類型化指針(typed pointer)轉變成無類型指針(untyped pointer),所以帶有const void* 指針的catch子句能捕獲任何

類型的指針類型異常:
catch (const void*) ... //可以捕獲所有指針異常
另外,你還可以用catch(...)來捕獲所有異常,注意是三個點。
傳遞參數和傳遞異常間最后一點差別是catch子句匹配順序總是取決于它們在程序中出現的順序。因此一個派生類異常可能被處
理其基類異常的catch子句捕獲,這叫異常截獲,一般的編譯器會有警告。

class A {
public:
A()
{
cout << "class A creates" << endl;
}
void print()
{
cout << "A" << endl;
}
~A()
{
cout << "class A destruct" << endl;
}
};
class B: public A
{
public:
B()
{
cout << "class B create" << endl;
}
void print()
{
cout << "B" << endl;
}
~B()
{
cout << "class B destruct" << endl;
}
};
void func()
{
??? B b;
??? throw b;
}
try
{
??? func();
}
catch( B& b) //必須將B放前面,如果把A放前面,B放后面,那么B類型的異常會先被截獲。
{
??? b.print();
}
catch (A& a)
{
??? a.print() ;
}
----------------------------------------------------------------
1、基礎介紹
try
{
//程序中拋出異常
throw value;
}
catch(valuetype v)
{
//例外處理程序段
}
語法小結:throw拋出值,catch接受,當然,throw必須在“try語句塊”中才有效。

2、深入throw:
(i)、程序接受到throw語句后就會自動調用析構器,把該域(try后的括號內)對象clean up,然后再進
入catch語句(如果在循環體中就退出循環)。

這種機制會引起一些致命的錯誤,比如,當“類”有指針成員變量時(又是指針!),在 “類的構建器
”中的throw語句引起的退出,會導致這個指針所指向的對象沒有被析構。這里很基礎,就不深入了,提
示一下,把指針改為類就行了,比如模板類來代替指針,在模板類的內部設置一個析構函數。

(ii)、語句“throw;”拋出一個無法被捕獲的異常,即使是catch(...)也不能捕捉到,這時進入終止函數
,見下catch。

3、深入catch:
一般的catch出現的形式是:
try{}
catch(except1&){}
catch(except2&){}
catch(...){} //接受所有異常
一般都寫成引用(except1&),原因很簡單,效率。

問題a:拋出異常,但是catch不到異常怎么辦?(注意沒有java類似的finally語句)
在catch沒有捕獲到匹配的異常的時候,會調用默認的終止函數。可以調用set_terminate()來設置終止函數,參數是一個函數指針,類型是

:void (*terminate)()。

到這里,可以題個問題:“沒有try-catch,直接在程序中"throw;",會怎么樣?”


其他一些技巧:
4、try一個函數體,形式如下
void fun(type1,type2) try----try放在函數體后
{
? 函數定義
}
catch(typeX){}
這個用法的效果就相當于:
void fun()?
{
? try{函數定義}
}


5、throw一個函數體,形式如下:
void fun (); // 能拋出任何類型的異常
void fun () throw(except1,except2,except3)?
?????????????????? // 后面括號里面是一個異常參數表,本例中只能拋出這3中異常
void fun () throw()? // 參數表為空,不能拋出異常

問題b:假設fun()中拋出了一個不在“異常參數表”中的異常,會怎么樣?

答:調用set_terminate()中設定的終止函數。然而,這只是表面現象,實際上是調用默認的unexpected()函數,然而這個默認的

unexpected()調用了set_terminate()中設定的終止函數。可以用set_unexpected()來設置unexpected,就像set_terminate()一樣的用法,但

是在設定了新的“unexpected()”之后,就不會再調用set_terminater中設定的終止函數了。

這個語法是很有用的,因為在用別人的代碼時,不知道哪個地方會調用什么函數又會拋出什么異常,用一個異常參數表在申明時限制一下,

很實用。

總結

以上是生活随笔為你收集整理的c++异常Try catch的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。