免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

中trycatch方法怎么在c++中使用

本篇文章為大家展示了中try catch方法怎么在c++中使用,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

專注于為中小企業(yè)提供成都網(wǎng)站制作、網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)海南州免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了超過(guò)千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

在c++中,可以直接拋出異常之后自己進(jìn)行捕捉處理,如:(這樣就可以在任何自己得到不想要的結(jié)果的時(shí)候進(jìn)行中斷,比如在進(jìn)行數(shù)據(jù)庫(kù)事務(wù)操作的時(shí)候,如果某一個(gè)語(yǔ)句返回SQL_ERROR則直接拋出異常,在catch塊中進(jìn)行事務(wù)回滾(回滾怎么理解?))。

#include <iostream> 
#include <exception> 
using namespace std; 
int main () { 
 try 
 { 
  throw 1; 
  throw "error"; 
 } 
 catch(char *str) 
 { 
  cout << str << endl; 
 } 
 catch(int i) 
 { 
  cout << i << endl; 
 } 
}

也可以自己定義異常類來(lái)進(jìn)行處理:

#include <iostream> 
#include <exception> 
using namespace std; 
 
//可以自己定義Exception 
class myexception: public exception 
{ 
 virtual const char* what() const throw() 
 { 
  return "My exception happened"; 
 } 
}myex; 
 
int main () { 
 try 
 {  
  if(true) //如果,則拋出異常; 
   throw myex; 
 } 
 catch (exception& e) 
 { 
  cout << e.what() << endl; 
 } 
 return 0; 
}

同時(shí)也可以使用標(biāo)準(zhǔn)異常類進(jìn)行處理:

#include <iostream> 
#include <exception> 
using namespace std; 
 
int main () { 
 try 
 { 
  int* myarray= new int[100000]; 
 } 
 catch (exception& e) 
 { 
  cout << "Standard exception: " << e.what() << endl; 
 } 
 return 0; 
}

一、簡(jiǎn)單的例子

首先通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)熟悉C++ 的 try/catch/throw(可根據(jù)單步調(diào)試來(lái)熟悉,try catch throw部分是如何運(yùn)行的):

#include <stdlib.h>
#include "iostream"
using namespace std;

double fuc(double x, double y)      //定義函數(shù)
{
 if(y==0)
 {
  throw y;         //除數(shù)為0,拋出異常
 }
 return x/y;         //否則返回兩個(gè)數(shù)的商
}

int _tmain(int argc, _TCHAR* argv[])
{
 double res;
 try           //定義異常
 {
  res=fuc(2,3);
  cout<<"The result of x/y is : "<<res<<endl;
  res=fuc(4,0);        //出現(xiàn)異常
 }
 catch(double)         //捕獲并處理異常
 {
  cerr<<"error of dividing zero.\n";
  exit(1);         //異常退出程序
 }
 return 0;
}

catch 的數(shù)據(jù)類型需要與throw出來(lái)的數(shù)據(jù)類型相匹配的。

二、catch(...)的作用

catch(…)能夠捕獲多種數(shù)據(jù)類型的異常對(duì)象,所以它提供給程序員一種對(duì)異常對(duì)象更好的控制手段,使開(kāi)發(fā)的軟件系統(tǒng)有很好的可靠性。因此一個(gè)比較有經(jīng)驗(yàn)的程序員通常會(huì)這樣組織編寫(xiě)它的代碼模塊,如下:

void Func()
{
  try
  {
    // 這里的程序代碼完成真正復(fù)雜的計(jì)算工作,這些代碼在執(zhí)行過(guò)程中
    // 有可能拋出DataType1、DataType2和DataType3類型的異常對(duì)象。
  }
  catch(DataType1& d1)
  {
  }
  catch(DataType2& d2)
  {
  }
  catch(DataType3& d3)
  {
  }
  /*********************************************************  注意上面try block中可能拋出的DataType1、DataType2和DataType3三
  種類型的異常對(duì)象在前面都已經(jīng)有對(duì)應(yīng)的catch block來(lái)處理。但為什么
  還要在最后再定義一個(gè)catch(…) block呢?這就是為了有更好的安全性和
  可靠性,避免上面的try block拋出了其它未考慮到的異常對(duì)象時(shí)導(dǎo)致的程
  序出現(xiàn)意外崩潰的嚴(yán)重后果,而且這在用VC開(kāi)發(fā)的系統(tǒng)上更特別有效,因
  為catch(…)能捕獲系統(tǒng)出現(xiàn)的異常,而系統(tǒng)異常往往令程序員頭痛了,現(xiàn)
  在系統(tǒng)一般都比較復(fù)雜,而且由很多人共同開(kāi)發(fā),一不小心就會(huì)導(dǎo)致一個(gè)
  指針變量指向了其它非法區(qū)域,結(jié)果意外災(zāi)難不幸發(fā)生了。catch(…)為這種
  潛在的隱患提供了一種有效的補(bǔ)救措施。  *********************************************************/
  catch(…)
  {
  }
}

三、異常中采用面向?qū)ο蟮奶幚?/strong>

首先看下面的例子:

void OpenFile(string f)
{
 try
  {
   // 打開(kāi)文件的操作,可能拋出FileOpenException
  }
  catch(FileOpenException& fe)
  {
   // 處理這個(gè)異常,如果這個(gè)異常可以很好的得以恢復(fù),那么處理完畢后函數(shù)
   // 正常返回;否則必須重新拋出這個(gè)異常,以供上層的調(diào)用函數(shù)來(lái)能再次處
    // 理這個(gè)異常對(duì)象
   int result = ReOpenFile(f);
   if (result == false) throw;
  }
}

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

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

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

下面是更多面向?qū)ο蠛彤惓L幚斫Y(jié)合的例子:

#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 (這里是異常處理空間中對(duì)異常類的拷貝的析構(gòu))
Destruct Test
======================================

不過(guò)一般來(lái)說(shuō)我們可能更習(xí)慣于把會(huì)產(chǎn)生異常的語(yǔ)句和要throw的異常類分成不同的類來(lái)寫(xiě),下面的代碼可以是我們更愿意書(shū)寫(xiě)的:

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; //這行不會(huì)執(zhí)行
 }
 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

四、構(gòu)造和析構(gòu)中的異常拋出

先看個(gè)程序,假如我在構(gòu)造函數(shù)的地方拋出異常,這個(gè)類的析構(gòu)會(huì)被調(diào)用嗎?可如果不調(diào)用,那類里的東西豈不是不能被釋放了?

#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(...)
  {}
}

結(jié)果為:
ExceptionClass1()
throw a exception

在這兩句輸出之間,我們已經(jīng)給S分配了內(nèi)存,但內(nèi)存沒(méi)有被釋放(因?yàn)樗窃谖鰳?gòu)函數(shù)中釋放的)。應(yīng)該說(shuō)這符合實(shí)際現(xiàn)象,因?yàn)閷?duì)象沒(méi)有完整構(gòu)造。

為了避免這種情況,我想你也許會(huì)說(shuō):應(yīng)避免對(duì)象通過(guò)本身的構(gòu)造函數(shù)涉及到異常拋出。即:既不在構(gòu)造函數(shù)中出現(xiàn)異常拋出,也不應(yīng)在構(gòu)造函數(shù)調(diào)用的一切東西中出現(xiàn)異常拋出。
但是在C++中可以在構(gòu)造函數(shù)中拋出異常,經(jīng)典的解決方案是使用STL的標(biāo)準(zhǔn)類auto_ptr。

那么,在析構(gòu)函數(shù)中的情況呢?我們已經(jīng)知道,異常拋出之后,就要調(diào)用本身的析構(gòu)函數(shù),如果這析構(gòu)函數(shù)中還有異常拋出的話,則已存在的異常尚未被捕獲,會(huì)導(dǎo)致異常捕捉不到。

五、標(biāo)準(zhǔn)C++異常類

標(biāo)準(zhǔn)異常都派生自一個(gè)公共的基類exception。基類包含必要的多態(tài)性函數(shù)提供異常描述,可以被重載。下面是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++有很多的標(biāo)準(zhǔn)異常類:
namespace std
{
 //exception派生
 class logic_error; //邏輯錯(cuò)誤,在程序運(yùn)行前可以檢測(cè)出來(lái)
 
 //logic_error派生
 class domain_error; //違反了前置條件
 class invalid_argument; //指出函數(shù)的一個(gè)無(wú)效參數(shù)
 class length_error; //指出有一個(gè)超過(guò)類型size_t的最大可表現(xiàn)值長(zhǎng)度的對(duì)象的企圖
 class out_of_range; //參數(shù)越界
 class bad_cast; //在運(yùn)行時(shí)類型識(shí)別中有一個(gè)無(wú)效的dynamic_cast表達(dá)式
 class bad_typeid; //報(bào)告在表達(dá)試typeid(*p)中有一個(gè)空指針p
 
 //exception派生
 class runtime_error; //運(yùn)行時(shí)錯(cuò)誤,僅在程序運(yùn)行中檢測(cè)到
 
 //runtime_error派生
 class range_error; //違反后置條件
 class overflow_error; //報(bào)告一個(gè)算術(shù)溢出
 class bad_alloc; //存儲(chǔ)分配錯(cuò)誤
}

標(biāo)準(zhǔn)庫(kù)異常類定義在以下四個(gè)頭文件中

1、exception頭文件:定義了最常見(jiàn)的標(biāo)準(zhǔn)異常類,其類名為exception。只通知異常的產(chǎn)生,但不會(huì)提供更多的信息

2、stdexcept頭文件定義了以下幾種常見(jiàn)異常類

函數(shù)   功能或作用

exception 最常見(jiàn)的問(wèn)題

runtime_error 運(yùn)行時(shí)錯(cuò)誤:僅在運(yùn)行時(shí)才能檢測(cè)到的問(wèn)題

range_error 運(yùn)行時(shí)錯(cuò)誤:生成的結(jié)果超出了有意義的值域范圍

overflow_error 運(yùn)行時(shí)錯(cuò)誤:計(jì)算上溢

underflow_error 運(yùn)行時(shí)錯(cuò)誤:計(jì)算下溢

logic_error 邏輯錯(cuò)誤:可在運(yùn)行前檢測(cè)到的問(wèn)題

domain_error 邏輯錯(cuò)誤:參數(shù)的結(jié)果值不存在

invalid_argument 邏輯錯(cuò)誤:不合適的參數(shù)

length_error 邏輯錯(cuò)誤:試圖生成一個(gè)超出該類型最大長(zhǎng)度的對(duì)象

out_of_range 邏輯錯(cuò)誤:使用一個(gè)超出有效范圍的值

3、new頭文件定義了bad_alloc異常類型,提供因無(wú)法分配內(nèi)存而由new拋出的異常

4、type_info頭文件定義了bad_cast異常類型(要使用type_info必須包含typeinfo頭文件)

下面是使用異常類的例子:

首先,我定義了幾個(gè)異常類,這些類也可以從標(biāo)準(zhǔn)異常類進(jìn)行派生,如下

class BadInitializers
{
public:
 BadInitializers() {}
};
class OutOfBounds
{
public:
 OutOfBounds(int i) { cout<<"Size "<<i<<" is illegal!!!"<<endl; }
};
class SizeMismatch
{
public:
 SizeMismatch() {}
};

然后要在程序中需要的地方使用throw來(lái)拋出異常類,兩個(gè)拋出異常類的例子如下

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...來(lái)捕獲異常,并進(jìn)行相應(yīng)的處理,如下

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://保護(hù)塊
}
__finally
{
file://結(jié)束處理程序
}
在上面的代碼段中,操作系統(tǒng)和編譯程序共同來(lái)確保結(jié)束處理程序中的__f i n a l l y代碼塊能夠被執(zhí)行,不管保護(hù)體(t r y塊)是如何退出的。不論你在保護(hù)體中使用r e t u r n,還是g o t o,或者是longjump,結(jié)束處理程序(f i n a l l y塊)都將被調(diào)用。

我們來(lái)看一個(gè)實(shí)列:(返回值:10, 沒(méi)有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;
}

這段代碼應(yīng)該只是做為一個(gè)基礎(chǔ)函數(shù),我們將在后面修改它,來(lái)看看結(jié)束處理程序的作用:
====================
在代碼加一句:(返回值:5, 沒(méi)有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塊的末尾增加了一個(gè)return語(yǔ)句。這個(gè)return語(yǔ)句告訴編譯程序在這里要退出這個(gè)函數(shù)并返回dwTemp變量的內(nèi)容,現(xiàn)在這個(gè)變量的值是5。但是,如果這個(gè)return語(yǔ)句被執(zhí)行,該線程將不會(huì)釋放信標(biāo),其他線程也就不能再獲得對(duì)信標(biāo)的控制。可以想象,這樣的執(zhí)行次序會(huì)產(chǎn)生很大的問(wèn)題,那些等待信標(biāo)的線程可能永遠(yuǎn)不會(huì)恢復(fù)執(zhí)行。
通過(guò)使用結(jié)束處理程序,可以避免return語(yǔ)句的過(guò)早執(zhí)行。當(dāng)return語(yǔ)句試圖退出try塊時(shí),編譯程序要確保finally塊中的代碼首先被執(zhí)行。要保證finally塊中的代碼在try塊中的return語(yǔ)句退出之前執(zhí)行。在程序中,將ReleaseSemaphore的調(diào)用放在結(jié)束處理程序塊中,保證信標(biāo)總會(huì)被釋放。這樣就不會(huì)造成一個(gè)線程一直占有信標(biāo),否則將意味著所有其他等待信標(biāo)的線程永遠(yuǎn)不會(huì)被分配CPU時(shí)間。
在finally塊中的代碼執(zhí)行之后,函數(shù)實(shí)際上就返回。任何出現(xiàn)在finally塊之下的代碼將不再執(zhí)行,因?yàn)楹瘮?shù)已在try塊中返回。所以這個(gè)函數(shù)的返回值是5,而不是10。
讀者可能要問(wèn)編譯程序是如何保證在try塊可以退出之前執(zhí)行finally塊的。當(dāng)編譯程序檢查源代碼時(shí),它看到在try塊中有return語(yǔ)句。這樣,編譯程序就生成代碼將返回值(本例中是5)保存在一個(gè)編譯程序建立的臨時(shí)變量中。編譯程序然后再生成代碼來(lái)執(zhí)行f i n a l l y塊中包含的指令,這稱為局部展開(kāi)。更特殊的情況是,由于try塊中存在過(guò)早退出的代碼,從而產(chǎn)生局部展開(kāi),導(dǎo)致系統(tǒng)執(zhí)行finally塊中的內(nèi)容。在finally塊中的指令執(zhí)行之后,編譯程序臨時(shí)變量的值被取出并從函數(shù)中返回。
可以看到,要完成這些事情,編譯程序必須生成附加的代碼,系統(tǒng)要執(zhí)行額外的工作。

finally塊的總結(jié)性說(shuō)明

我們已經(jīng)明確區(qū)分了強(qiáng)制執(zhí)行finally塊的兩種情況:
? 從try塊進(jìn)入finally塊的正常控制流。
? 局部展開(kāi):從try塊的過(guò)早退出(goto、long jump、continue、break、return等)強(qiáng)制控制轉(zhuǎn)移到finally塊。
第三種情況,全局展開(kāi)( global unwind),這個(gè)以后再看。

七、C++異常參數(shù)傳遞

從語(yǔ)法上看,在函數(shù)里聲明參數(shù)與在catch子句中聲明參數(shù)是一樣的,catch里的參數(shù)可以是值類型,引用類型,指針類型。例如:

try
{
 .....
}
catch(A a)
{
}
catch(B& b)
{
}
catch(C* c)
{
}

盡管表面是它們是一樣的,但是編譯器對(duì)二者的處理卻又很大的不同。調(diào)用函數(shù)時(shí),程序的控制權(quán)最終還會(huì)返回到函數(shù)的調(diào)用處,但是拋出一個(gè)異常時(shí),控制權(quán)永遠(yuǎn)不會(huì)回到拋出異常的地方。

class A;
void func_throw()
{
  A a;
  throw a; //拋出的是a的拷貝,拷貝到一個(gè)臨時(shí)對(duì)象里
}
try
{
 func_throw();
}
catch(A a) //臨時(shí)對(duì)象的拷貝
{
}

當(dāng)我們拋出一個(gè)異常對(duì)象時(shí),拋出的是這個(gè)異常對(duì)象的拷貝。當(dāng)異常對(duì)象被拷貝時(shí),拷貝操作是由對(duì)象的拷貝構(gòu)造函數(shù)完成的。該拷貝構(gòu)造函數(shù)是對(duì)象的靜態(tài)類型(static type)所對(duì)應(yīng)類的拷貝構(gòu)造函數(shù),而不是對(duì)象的動(dòng)態(tài)類型(dynamic type)對(duì)應(yīng)類的拷貝構(gòu)造函數(shù)。此時(shí)對(duì)象會(huì)丟失RTTI信息。

異常是其它對(duì)象的拷貝,這個(gè)事實(shí)影響到你如何在catch塊中再拋出一個(gè)異常。比如下面這兩個(gè)catch塊,乍一看好像一樣:

catch (A& w) // 捕獲異常
{
 // 處理異常
 throw; // 重新拋出異常,讓它繼續(xù)傳遞
}
catch (A& w) // 捕獲Widget異常
{
 // 處理異常
 throw w; // 傳遞被捕獲異常的拷貝
}

第一個(gè)塊中重新拋出的是當(dāng)前異常(current exception),無(wú)論它是什么類型。(有可能是A的派生類)  
  第二個(gè)catch塊重新拋出的是新異常,失去了原來(lái)的類型信息。
  一般來(lái)說(shuō),你應(yīng)該用throw來(lái)重新拋出當(dāng)前的異常,因?yàn)檫@樣不會(huì)改變被傳遞出去的異常類型,而且更有效率,因?yàn)椴挥蒙梢粋€(gè)新拷貝。
看看以下這三種聲明:
catch (A w) ... // 通過(guò)傳值
catch (A& w) ... // 通過(guò)傳遞引用,一個(gè)被異常拋出的對(duì)象(總是一個(gè)臨時(shí)對(duì)象)可以通過(guò)普通的引用捕獲
catch (const A& w) ... //const引用

catch (A w) ... // 通過(guò)傳值捕獲
會(huì)建立兩個(gè)被拋出對(duì)象的拷貝,一個(gè)是所有異常都必須建立的臨時(shí)對(duì)象,第二個(gè)是把臨時(shí)對(duì)象拷貝進(jìn)w中。實(shí)際上,編譯器會(huì)優(yōu)化掉一個(gè)拷貝。同樣,當(dāng)我們通過(guò)引用捕獲異常時(shí),
catch (A& w) ... // 通過(guò)引用捕獲
catch (const A& w) ... //const引用捕獲
這仍舊會(huì)建立一個(gè)被拋出對(duì)象的拷貝:拷貝是一個(gè)臨時(shí)對(duì)象。相反當(dāng)我們通過(guò)引用傳遞函數(shù)參數(shù)時(shí),沒(méi)有進(jìn)行對(duì)象拷貝。話雖如此,但是不是所有編譯器都如此。 

通過(guò)指針拋出異常與通過(guò)指針傳遞參數(shù)是相同的。不論哪種方法都是一個(gè)指針的拷貝被傳遞。你不能認(rèn)為拋出的指針是一個(gè)指向局部對(duì)象的指針,因?yàn)楫?dāng)異常離開(kāi)局部變量的生存空間時(shí),該局部變量已經(jīng)被釋放。Catch子句將獲得一個(gè)指向已經(jīng)不存在的對(duì)象的指針。這種行為在設(shè)計(jì)時(shí)應(yīng)該予以避免。
  另外一個(gè)重要的差異是在函數(shù)調(diào)用者或拋出異常者與被調(diào)用者或異常捕獲者之間的類型匹配的過(guò)程不同。在函數(shù)傳遞參數(shù)時(shí),如果參數(shù)不匹配,那么編譯器會(huì)嘗試一個(gè)類型轉(zhuǎn)換,如果存在的話。而對(duì)于異常處理的話,則完全不是這樣。見(jiàn)一下的例子:

void func_throw()
{
  CString a;
  throw a; //拋出的是a的拷貝,拷貝到一個(gè)臨時(shí)對(duì)象里
}

try
{
func_throw();
}
catch(const char* s)
{
}

盡管如此,在catch子句中進(jìn)行異常匹配時(shí)可以進(jìn)行兩種類型轉(zhuǎn)換。第一種是基類與派生類的轉(zhuǎn)換,一個(gè)用來(lái)捕獲基類的catch子句也可以處理派生類類型的異常。反過(guò)來(lái),用來(lái)捕獲派生類的無(wú)法捕獲基類的異常。
  第二種是允許從一個(gè)類型化指針(typed pointer)轉(zhuǎn)變成無(wú)類型指針(untyped pointer),所以帶有const void* 指針的catch子句能捕獲任何類型的指針類型異常:
catch (const void*) ... //可以捕獲所有指針異常
  另外,你還可以用catch(...)來(lái)捕獲所有異常,注意是三個(gè)點(diǎn)。
  傳遞參數(shù)和傳遞異常間最后一點(diǎn)差別是catch子句匹配順序總是取決于它們?cè)诔绦蛑谐霈F(xiàn)的順序。因此一個(gè)派生類異常可能被處理其基類異常的catch子句捕獲,這叫異常截獲,一般的編譯器會(huì)有警告。

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類型的異常會(huì)先被截獲。
{
 b.print();
}
catch (A& a)
{
 a.print() ;
}

上述內(nèi)容就是中try catch方法怎么在c++中使用,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

本文題目:中trycatch方法怎么在c++中使用
轉(zhuǎn)載來(lái)于:http://m.newbst.com/article4/gdocoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)手機(jī)網(wǎng)站建設(shè)建站公司網(wǎng)站策劃網(wǎng)站營(yíng)銷企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)