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

C++中異常處理的基本思想及throw語句拋出異常的使用

 更新時(shí)間:2016年03月14日 15:38:20   作者:YoferZhang  
這篇文章主要介紹了C++中異常處理的基本思想及throw類拋出異常的使用,也深入談到了異常被拋出后的棧解旋unwinding過程,需要的朋友可以參考下

異常處理基本思想
C++的異常處理的基本思想大致可以概括為傳統(tǒng)錯(cuò)誤處理機(jī)制、通過函數(shù)返回值來處理錯(cuò)誤。

2016314153351173.jpg (377×335)

1)C++的異常處理機(jī)制使得異常的引發(fā)和異常的處理不必在同一個(gè)函數(shù)中,這樣底層的函數(shù)可以著重解決具體問題,而不必過多的考慮異常的處理。上層調(diào)用者可以再適當(dāng)?shù)奈恢迷O(shè)計(jì)對不同類型異常的處理。
2)異常是專門針對抽象編程中的一系列錯(cuò)誤處理的,C++中不能借助函數(shù)機(jī)制,因?yàn)闂=Y(jié)構(gòu)的本質(zhì)是先進(jìn)后出,依次訪問,無法進(jìn)行跳躍,但錯(cuò)誤處理的特征卻是遇到錯(cuò)誤信息就想要轉(zhuǎn)到若干級之上進(jìn)行重新嘗試,如圖

3)異常超脫于函數(shù)機(jī)制,決定了其對函數(shù)的跨越式回跳。
4)異??缭胶瘮?shù)

異?;菊Z法

2016314153429533.jpg (577×329)

1) 若有異常則通過throw操作創(chuàng)建一個(gè)異常對象并拋擲。
2) 將可能拋出異常的程序段嵌在try塊之中??刂仆ㄟ^正常的順序執(zhí)行到達(dá)try語句,然后執(zhí)行try塊內(nèi)的保護(hù)段。
3) 如果在保護(hù)段執(zhí)行期間沒有引起異常,那么跟在try塊后的catch子句就不執(zhí)行。程序從try塊后跟隨的最后一個(gè)catch子句后面的語句繼續(xù)執(zhí)行下去。
4) catch子句按其在try塊后出現(xiàn)的順序被檢查。匹配的catch子句將捕獲并處理異常(或繼續(xù)拋擲異常)。
5) 如果匹配的處理器未找到,則運(yùn)行函數(shù)terminate將被自動調(diào)用,其缺省功能是調(diào)用abort終止程序。
6)處理不了的異常,可以在catch的最后一個(gè)分支,使用throw語法,向上扔
7)異常機(jī)制與函數(shù)機(jī)制互不干涉,但捕捉的方式是基于類型匹配。捕捉相當(dāng)于函數(shù)返回類型的匹配,而不是函數(shù)參數(shù)的匹配,所以捕捉不用考慮一個(gè)拋擲中的多種數(shù)據(jù)類型匹配問題。
catch代碼塊必須出現(xiàn)在try后,并且在try塊后可以出現(xiàn)多個(gè)catch代碼塊,以捕捉各種不同類型的拋擲。
異常機(jī)制是基于這樣的原理:程序運(yùn)行實(shí)質(zhì)上是數(shù)據(jù)實(shí)體在做一些操作,因此發(fā)生異?,F(xiàn)象的地方,一定是某個(gè)實(shí)體出了差錯(cuò),該實(shí)體所對應(yīng)的數(shù)據(jù)類型便作為拋擲和捕捉的依據(jù)。
8)異常捕捉嚴(yán)格按照類型匹配
 異常捕捉的類型匹配之苛刻程度可以和模板的類型匹配媲美,它不允許相容類型的隱式轉(zhuǎn)換,比如,拋擲char類型用int型就捕捉不到.例如下列代碼不會輸出“int exception.”,從而也不會輸出“That's ok.” 因?yàn)槌霈F(xiàn)異常后提示退出

int main(){ 
  try{ 
    throw ‘H'; 
  } 
  catch (int){ 
    cout << "int exception.\n"; 
  } 
  cout << "That's ok.\n"; 
 
  return 0; 
} 

棧解旋(unwinding)
異常被拋出后,從進(jìn)入try塊起,到異常被拋擲前,這期間在棧上的構(gòu)造的所有對象,都會被自動析構(gòu)。析構(gòu)的順序與構(gòu)造的順序相反。這一過程稱為棧的解旋(unwinding)。

#include <iostream> 
#include <cstdio> 
using namespace std; 
 
 
class MyException {}; 
 
class Test 
{ 
public: 
  Test(int a = 0, int b = 0) 
  { 
    this->a = a; 
    this->b = b; 
    cout << "Test 構(gòu)造函數(shù)執(zhí)行" << "a:" << a << " b: " << b << endl; 
  } 
  void printT() 
  { 
    cout << "a:" << a << " b: " << b << endl; 
  } 
  ~Test() 
  { 
    cout << "Test 析構(gòu)函數(shù)執(zhí)行" << "a:" << a << " b: " << b << endl; 
  } 
private: 
  int a; 
  int b; 
}; 
 
void myFunc() throw (MyException) 
{ 
  Test t1; 
  Test t2; 
 
  cout << "定義了兩個(gè)棧變量,異常拋出后測試棧變量的如何被析構(gòu)" << endl; 
 
  throw MyException(); 
} 
 
int main() 
{ 
  //異常被拋出后,從進(jìn)入try塊起,到異常被拋擲前,這期間在棧上的構(gòu)造的所有對象, 
  //都會被自動析構(gòu)。析構(gòu)的順序與構(gòu)造的順序相反。 
  //這一過程稱為棧的解旋(unwinding) 
  try 
  { 
    myFunc(); 
  } 
  //catch(MyException &e) //這里不能訪問異常對象 
  catch (MyException) //這里不能訪問異常對象 
  { 
    cout << "接收到MyException類型異常" << endl; 
  } 
  catch (...) 
  { 
    cout << "未知類型異常" << endl; 
  } 
 
  return 0; 
} 

異常接口聲明
1)為了加強(qiáng)程序的可讀性,可以在函數(shù)聲明中列出可能拋出的所有異常類型,例如:
void func() throw (A, B, C , D); //這個(gè)函數(shù)func()能夠且只能拋出類型A B C D及其子類型的異常。
2)如果在函數(shù)聲明中沒有包含異常接口聲明,則次函數(shù)可以拋擲任何類型的異常,例如:
void func();
3)一個(gè)不拋擲任何類型異常的函數(shù)可以聲明為:
void func() throw();
4) 如果一個(gè)函數(shù)拋出了它的異常接口聲明所不允許拋出的異常,unexpected函數(shù)會被調(diào)用,該函數(shù)默認(rèn)行為調(diào)用terminate函數(shù)中止程序。

傳統(tǒng)處理錯(cuò)誤

#include <iostream> 
#include <cstdio> 
using namespace std; 
 
// 傳統(tǒng)的錯(cuò)誤處理機(jī)制 
int myStrcpy(char *to, char *from) 
{ 
  if (from == NULL) { 
    return 1; 
  } 
  if (to == NULL) { 
    return 2; 
  } 
 
  // copy時(shí)的場景檢查 
  if (*from == 'a') { 
    return 3; // copy時(shí)錯(cuò)誤 
  } 
  while (*from != '\0') { 
    *to = *from; 
    to++; 
    from++; 
  } 
  *to = '\0'; 
 
  return 0; 
} 
 
int main() 
{ 
  int ret = 0; 
  char buf1[] = "zbcdefg"; 
  char buf2[1024] = { 0 }; 
 
  ret = myStrcpy(buf2, buf1); 
  if (ret != 0) { 
    switch (ret) { 
    case 1: 
      cout << "源buf出錯(cuò)!\n"; 
      break; 
    case 2: 
      cout << "目的buf出錯(cuò)!\n"; 
      break; 
    case 3: 
      cout << "copy過程出錯(cuò)!\n"; 
      break; 
    default: 
      cout << "未知錯(cuò)誤!\n"; 
      break; 
    } 
  } 
  cout << "buf2:\n" << buf2; 
  cout << endl; 
 
  return 0; 
} 

throw char*

#include <iostream> 
#include <cstdio> 
using namespace std; 
 
// throw char * 
void myStrcpy(char *to, char *from) 
{ 
  if (from == NULL) { 
    throw "源buf出錯(cuò)"; 
  } 
  if (to == NULL) { 
    throw "目的buf出錯(cuò)"; 
  } 
 
  // copy時(shí)的場景檢查 
  if (*from == 'a') { 
    throw "copy過程出錯(cuò)"; // copy時(shí)錯(cuò)誤 
  } 
  while (*from != '\0') { 
    *to = *from; 
    to++; 
    from++; 
  } 
  *to = '\0'; 
 
  return; 
} 
 
int main() 
{ 
  int ret = 0; 
  char buf1[] = "abcdefg"; 
  char buf2[1024] = { 0 }; 
 
  try 
  { 
    myStrcpy(buf2, buf1); 
  } 
  catch (int e) // e可以寫可以不寫 
  { 
    cout << e << "int類型異常" << endl; 
  } 
  catch (char *e) 
  { 
    cout << "char* 類型異常" << endl; 
  } 
  catch (...) 
  { 
  }; 
  cout << endl; 
 
  return 0; 
} 

throw 類對象

#include <iostream> 
#include <cstdio> 
using namespace std; 
 
class BadSrcType {}; 
class BadDestType {}; 
class BadProcessType 
{ 
public: 
  BadProcessType() 
  { 
    cout << "BadProcessType構(gòu)造函數(shù)do \n"; 
  } 
 
 
  BadProcessType(const BadProcessType &obj) 
  { 
    cout << "BadProcessType copy構(gòu)造函數(shù)do \n"; 
  } 
 
  ~BadProcessType() 
  { 
    cout << "BadProcessType析構(gòu)函數(shù)do \n"; 
  } 
 
}; 

 
throw 類對象、類型異常 

void my_strcpy3(char *to, char *from) 
{ 
  if (from == NULL) 
  { 
    throw BadSrcType(); 
  } 
  if (to == NULL) 
  { 
    throw BadDestType(); 
  } 
 
  //copy是的 場景檢查 
  if (*from == 'a') 
  { 
    printf("開始 BadProcessType類型異常 \n"); 
    throw BadProcessType(); //會不會產(chǎn)生一個(gè)匿名對象? 
  } 
 
  if (*from == 'b') 
  { 
    throw &(BadProcessType()); //會不會產(chǎn)生一個(gè)匿名對象? 
  } 
 
  if (*from == 'c') 
  { 
    throw new BadProcessType; //會不會產(chǎn)生一個(gè)匿名對象? 
  } 
  while (*from != '\0') 
  { 
    *to = *from; 
    to++; 
    from++; 
  } 
  *to = '\0'; 
} 
 
int main() 
{ 
  int ret = 0; 
  char buf1[] = "cbbcdefg"; 
  char buf2[1024] = { 0 }; 
 
  try 
  { 
    //my_strcpy1(buf2, buf1); 
    //my_strcpy2(buf2, buf1); 
    my_strcpy3(buf2, buf1); 
  } 
  catch (int e) //e可以寫 也可以不寫 
  { 
    cout << e << " int類型異常" << endl; 
  } 
  catch (char *e) 
  { 
    cout << e << " char* 類型異常" << endl; 
  } 
 
  //--- 
  catch (BadSrcType e) 
  { 
    cout << " BadSrcType 類型異常" << endl; 
  } 
  catch (BadDestType e) 
  { 
    cout << " BadDestType 類型異常" << endl; 
  } 
  //結(jié)論1: 如果 接受異常的時(shí)候 使用一個(gè)異常變量,則copy構(gòu)造異常變量.  
  /* 
  catch( BadProcessType e) //是把匿名對象copy給e 還是e還是那個(gè)匿名對象 
  { 
  cout << " BadProcessType 類型異常" << endl; 
  } 
  */ 
  /*結(jié)論2: 使用引用的話 會使用throw時(shí)候的那個(gè)對象 
  catch( BadProcessType &e) //是把匿名對象copy給e 還是e還是那個(gè)匿名對象 
  { 
  cout << " BadProcessType 類型異常" << endl; 
  } 
  */ 
 
  //結(jié)論3: 指針可以和引用/元素寫在一塊 但是引用和元素不能寫在一塊 
  catch (BadProcessType *e) //是把匿名對象copy給e 還是e還是那個(gè)匿名對象 
  { 
    cout << " BadProcessType 類型異常" << endl; 
    delete e; 
  } 
 
  //結(jié)論4: 類對象時(shí), 使用引用比較合適  
 
  // -- 
  catch (...) 
  { 
    cout << "未知 類型異常" << endl; 
  } 
 
  return 0; 
} 


相關(guān)文章

  • C/C++整數(shù)乘積的溢出問題的解決

    C/C++整數(shù)乘積的溢出問題的解決

    整數(shù)乘積的溢出問題是指兩個(gè)整數(shù)相乘得到的結(jié)果超過了所能表示的數(shù)據(jù)類型的范圍,本文給大家介紹了C/C++整數(shù)乘積的溢出問題的解決,需要的朋友可以參考下
    2024-02-02
  • 判斷一個(gè)數(shù)是不是素?cái)?shù)的方法

    判斷一個(gè)數(shù)是不是素?cái)?shù)的方法

    判斷一個(gè)數(shù)是不是素?cái)?shù)的方法,需要的朋友可以參考一下
    2013-03-03
  • String類的寫時(shí)拷貝實(shí)例

    String類的寫時(shí)拷貝實(shí)例

    下面小編就為大家?guī)硪黄猄tring類的寫時(shí)拷貝實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • Qt繪制圖表的實(shí)現(xiàn)

    Qt繪制圖表的實(shí)現(xiàn)

    Qt中提供了強(qiáng)大的2D繪圖系統(tǒng),可以使用同一API實(shí)現(xiàn)在屏幕和繪圖設(shè)備上進(jìn)行繪制,本文就詳細(xì)的介紹了Qt繪制坐標(biāo)圖、柱狀圖、折線圖、餅圖、曲線圖、散點(diǎn)圖等,感興趣的可以了解一下
    2021-05-05
  • C語言自定義類型超詳細(xì)梳理之結(jié)構(gòu)體 枚舉 聯(lián)合體

    C語言自定義類型超詳細(xì)梳理之結(jié)構(gòu)體 枚舉 聯(lián)合體

    今天我們來學(xué)習(xí)一下自定義類型,自定義類型包括結(jié)構(gòu)體、枚舉、聯(lián)合體,小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考
    2022-03-03
  • C語言詳細(xì)講解位運(yùn)算符的使用

    C語言詳細(xì)講解位運(yùn)算符的使用

    C語?既具有?級語?的特點(diǎn),?具有低級語?的特性,如?持位運(yùn)算就是其具體體現(xiàn)。這是因?yàn)?,C語?最初是為取代匯編語?設(shè)計(jì)系統(tǒng)軟件?設(shè)計(jì)的,因此C語?必須?持位運(yùn)算等匯編操作。位運(yùn)算就是對字節(jié)或字內(nèi)的?進(jìn)制數(shù)位進(jìn)?測試、抽取、設(shè)置或移位等操作
    2022-04-04
  • c++中struct和class的區(qū)別小結(jié)

    c++中struct和class的區(qū)別小結(jié)

    在C++中,class和struct都是用于定義自定義數(shù)據(jù)類型的關(guān)鍵字,本文主要介紹了c++中struct和class的區(qū)別小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • C++調(diào)試追蹤class成員變量的方法

    C++調(diào)試追蹤class成員變量的方法

    本文所講的是不通過修改一個(gè)class的成員,就能夠追蹤其成員。方法就是類似C語言中的函數(shù)指針
    2013-11-11
  • 詳解c++ 繼承

    詳解c++ 繼承

    這篇文章主要介紹了c++ 繼承的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • VC++中HTControl控件類的CHTSlider控制桿控件類簡介

    VC++中HTControl控件類的CHTSlider控制桿控件類簡介

    這篇文章主要介紹了VC++中HTControl控件類的CHTSlider控制桿控件類,需要的朋友可以參考下
    2014-08-08

最新評論

陕西省| 德清县| 长丰县| 威远县| 鹤峰县| 大埔县| 仁布县| 正宁县| 恩平市| 安福县| 临高县| 凤庆县| 怀化市| 嘉鱼县| 石嘴山市| 新巴尔虎左旗| 浦县| 四会市| 佛坪县| 苗栗市| 商南县| 绥中县| 岳普湖县| 桓仁| 新和县| 文山县| 岑溪市| 安达市| 开封县| 富川| 平顶山市| 张掖市| 昌江| 梅河口市| 江口县| 嘉黎县| 凉山| 大竹县| 黄石市| 嘉黎县| 焉耆|