小城鎮(zhèn)建設(shè)的網(wǎng)站谷歌瀏覽器 官網(wǎng)下載
異常
異常是面向?qū)ο笳Z(yǔ)言處理錯(cuò)誤的一種方式。當(dāng)一個(gè)函數(shù)出現(xiàn)自己無(wú)法處理的錯(cuò)誤時(shí),可以拋出異常,然后輸?shù)闹苯踊蛘唛g接調(diào)用者處理這個(gè)錯(cuò)誤。
語(yǔ)法
捕獲全部的異常
try
{//可能拋出異常的代碼//throw異常對(duì)象
}
catch(...)
{//不管什么異常,都在這里統(tǒng)一處理
}
捕獲指定的異常
try
{// 可能拋出異常的代碼。// throw 異常對(duì)象;
}
catch (exception1 e)
{// 發(fā)生exception1異常時(shí)的處理代碼。
}
catch (exception2 e)
{// 發(fā)生exception2異常時(shí)的處理代碼。
}
在try語(yǔ)句塊中,如果沒(méi)有發(fā)生異常,執(zhí)行完try語(yǔ)句塊中的代碼后,將繼續(xù)執(zhí)行try語(yǔ)句塊之后的代碼;如果發(fā)生了異常,用throw拋出異常對(duì)象,異常對(duì)象的類型決定了應(yīng)該匹配到哪個(gè)catch語(yǔ)句塊,如果沒(méi)有匹配到catch語(yǔ)句塊,程序?qū)⒄{(diào)用abort()函數(shù)中止。
如果try語(yǔ)句塊中用throw拋出異常對(duì)象,并且匹配到了catch語(yǔ)句塊,執(zhí)行完catch語(yǔ)句塊中的代碼后,將繼續(xù)執(zhí)行catch語(yǔ)句塊之后的代碼,不會(huì)回到try語(yǔ)句塊中。
如果程序中的異常沒(méi)有被捕獲,程序?qū)惓V兄埂?/p>
catch是通過(guò)throw拋出的對(duì)象匹配的;
catch(...)可以捕獲任意類似的對(duì)象,主要捕獲自己都不知道的異常;
下面看幾個(gè)例子
try語(yǔ)句塊中代碼出現(xiàn)異常
#include<iostream>
#include<exception>
#include<array>
using namespace std;
void test()
{array<int, 5> a = { 1,2,3,4,5 };//try//{// int a1 = a[5];// cout << a1 << endl;//}//catch(exception e)//{// cout << "1越界了" << endl;//}try{int a2 = a.at(5);cout << a2 << endl;}catch (exception e){cout << "2越界了" << endl;}
}
int main()
{test();return 0;
}
這里由于第一個(gè)數(shù)組越界程序直接崩潰,注釋掉,運(yùn)行,結(jié)果如下

因?yàn)閍t會(huì)檢查是否越界,當(dāng)訪問(wèn)越界時(shí)會(huì)拋出異常,從而catch發(fā)揮作用。
try語(yǔ)句中拋出異常
#include<iostream>
#include<exception>
#include<array>
using namespace std;
void test1()
{try{throw"未知錯(cuò)誤";cout << "語(yǔ)句1" << endl;}catch (const char* e){cout << e << endl;}
}
int main()
{test1();return 0;
}
我們發(fā)現(xiàn)try語(yǔ)句塊中throw后面的語(yǔ)句沒(méi)有執(zhí)行,我們繼續(xù)觀察

try語(yǔ)句中的函數(shù)拋出異常
#include<iostream>
#include<exception>
#include<array>
using namespace std;
void func()
{throw"未知錯(cuò)誤!";cout << "func()中" << endl;
}
void test2()
{try{func();cout << "try中" << endl;}catch (const char* e){cout << e << endl;}
}
int main()
{test2();return 0;
}

這里我們發(fā)現(xiàn)try語(yǔ)句中拋出異常函數(shù)后面的語(yǔ)句和函數(shù)體拋出語(yǔ)句后面的語(yǔ)句沒(méi)有執(zhí)行。
這是為什么呢??
在函數(shù)調(diào)用鏈中異常展開匹配原則
1. 首先檢查 throw 本身是否在 try 塊內(nèi)部,如果是再查找匹配的 catch 語(yǔ)句,如果有匹配的,則調(diào)到catch的地方進(jìn)行處理;
2. 沒(méi)有匹配的catch則退出當(dāng)前函數(shù)棧,繼續(xù)在調(diào)用函數(shù)的棧中進(jìn)行查找匹配的catch;
3. 如果到達(dá)main函數(shù)的棧,依舊沒(méi)有匹配的,則終止程序。上述這個(gè)沿著調(diào)用鏈查找匹配的catch子句的 過(guò)程稱為棧展開,也稱棧解旋。所以實(shí)際中我們最后都要加一個(gè)catch(…)捕獲任意類型的異常,否則當(dāng)有異常沒(méi)捕獲,程序就會(huì)直接終止。
4. 找到匹配的catch子句并處理以后,會(huì)繼續(xù)沿著catch子句后面繼續(xù)執(zhí)行。
#include<iostream>
#include<exception>
using namespace std;
void func1()
{throw"多級(jí)函數(shù)調(diào)用的未知錯(cuò)誤";
}
void func2()
{func1();
}
void func3()
{func2();
}
void test3()
{try{func3();cout << "try中" << endl;}catch (...){cout << "未知錯(cuò)誤" << endl;}
}
int main()
{test3();return 0;
}

總結(jié):沒(méi)有找到匹配的函數(shù)棧就會(huì)被釋放。
把上述代碼進(jìn)行修改如下
#include<iostream>
#include<exception>
using namespace std;
void func1()
{throw"多級(jí)函數(shù)調(diào)用的未知錯(cuò)誤";}
void func2()
{try{func1();}catch(const char* e){cout << e << endl;}}
void func3()
{func2();
}
void test3()
{try{func3();cout << "try中" << endl;}catch (...){cout << "未知錯(cuò)誤" << endl;}
}
int main()
{test3();return 0;
}

多級(jí)catch
下面給出例子
#include<iostream>
using namespace std;
int main()
{cout << "1-錯(cuò)誤A,2-錯(cuò)誤B,other-未知錯(cuò)誤" << endl;cout << "請(qǐng)輸入:";int x = 0;while (cin >> x){try{if (x == 1)throw"錯(cuò)誤A";else if (x == 2)throw"錯(cuò)誤B";elsethrow"未知錯(cuò)誤";}catch(const char* e){cout << e << endl;}cout << "請(qǐng)輸入:";}return 0;
}