當(dāng)前位置:首頁 > 公眾號精選 > wenzi嵌入式軟件
[導(dǎo)讀]引言在前面的教程中,敘述了模板函數(shù)以及模板類的相關(guān)概念,在本節(jié)教程中,筆者將著重?cái)⑹?C中的異常機(jī)制,所謂異常,是程序在執(zhí)行期間產(chǎn)生的問題,異常提供一種轉(zhuǎn)移程序控制權(quán)的方式。而且異常處理主要涉及到三個關(guān)鍵字:try、catch、throw,下面將對異常這個概念進(jìn)行詳細(xì)敘述。異常的...

引言

在前面的教程中,敘述了模板函數(shù)以及模板類的相關(guān)概念,在本節(jié)教程中,筆者將著重?cái)⑹?C 中的異常機(jī)制,所謂異常,是程序在執(zhí)行期間產(chǎn)生的問題,異常提供一種轉(zhuǎn)移程序控制權(quán)的方式。而且異常處理主要涉及到三個關(guān)鍵字:try、catch、throw,下面將對異常這個概念進(jìn)行詳細(xì)敘述。

異常的引入

為什么要引入異常這個機(jī)制呢,假設(shè)有如下一個調(diào)用關(guān)系:

A?---->?B?---->?C
那如果說是,C函數(shù)中出現(xiàn)了一個問題,那要將這個問題找到,就需要在?C函數(shù)里返回一個值,然后根據(jù)這個值一級一級地向上處理,有多少層就要往上傳遞多少層,下面是偽代碼示意圖:

int?C()
{
????return?XXX;
}

int?B()
{
????if?(C())
????????{...}
????else
????????return?-Err;
}

int?A()
{
????if?(B())
????{...}
????else
????{/*處理問題*/}
}
由上述這樣一個偽代碼可以看出,如果通過返回值這樣地方式來處理子函數(shù)出現(xiàn)地問題的時候,那么當(dāng)函數(shù)調(diào)用很深的時候,這種處理方式的弊端也就顯現(xiàn)出來了,代碼會看起來很冗長,且略顯復(fù)雜,所以也就有了異常處理機(jī)制。

異常處理機(jī)制

在最開始講述這個概念的時候,我們依舊采用剛剛所述的那個背景,A ----> B ----> C,再有了異常機(jī)制之后,我們就可以用異常的處理機(jī)制來解決這個問題,那基于這樣一個背景,同樣是C函數(shù)里出現(xiàn)了問題,我們用依據(jù)話來概括異常,也就是函數(shù)A捕捉函數(shù)C發(fā)出的異常。我們將上述這句話進(jìn)行剖析也就剖析成如下這樣幾句話:

  • 1、誰捕捉異常?A

  • 2、誰拋出異常?C

  • 3、捕捉到異常怎么處理?隨A

基于上述這樣一個機(jī)制,我們來簡單地編寫一個異常處理代碼:

void?C()
{
????throw?1;
}

void?B()
{
????C();
}

void?A()
{
????try
????{
????????B();
????}?
????catch?(i)
????{
????????cout<<"catch?exception?"<endl;
????}
}
上述代碼啥意思呢,try后面接一個函數(shù)調(diào)用,它的意思實(shí)際也就是說,試著運(yùn)行一下B(),如果B()中存在問題,那么就捕獲這個錯誤,這里的catchC()函數(shù)里的throw 1是所對應(yīng)起來的。程序運(yùn)行結(jié)果如下所示:

image-20210226110245582
也就說,throw的值是多少,那么這里捕獲的變量也就是多少。

我們繼續(xù)豐富上面的代碼,如果說拋出的異常有很多個該如何進(jìn)行處理呢?我們同樣是基于剛才的背景進(jìn)行敘述,函數(shù)之間的調(diào)用關(guān)系跟上述一樣,我們給出各個函數(shù)的代碼:

void?C(int?i)
{
????int?a?=?1;
????double?b=?1.2;
????float?c?=?1.3;

????if?(i?==?0)
????{
????????cout<<"In?C,?it?is?OK"<<endl;
????}
????else?if?(i?==?1)
????????throw?a;
????else?if?(i?==?2)
????????throw?b;
????else?
????????throw?c;
}

void?B(int?i)
{
????cout<<"call?C?..."<<endl;
????C(i);
????cout<<"After?call?C"<<endl;
}

void?A(int?i)
{
????try?
????{
????????B(i);
????}?
????catch?(int?j)
????{
????????cout<<"catch?int?exception?"<endl;
????}?
????catch?(double?d)
????{
????????cout<<"catch?double?exception?"<endl;
????}?
????catch?(...){
????????cout<<"catch?other?exception?"<<endl;
????}
}
我們會根據(jù)傳入到?B()中的參數(shù),依次拋出不同類型的異常,然后去設(shè)置不同的捕獲方式,在編寫捕獲代碼的時候,涉及到其他的這個選項(xiàng),可以用...來替代,下面是主函數(shù)的代碼,:

int?main(int?argc,?char?**argv)
{
????int?i;

????if?(argc?!=?2)
????{
????????cout<<"Usage:?"<<endl;
????????cout<0]<<"?<0|1|2|3>"<<endl;
????????return?-1;
????}

????i?=?strtoul(argv[1],?NULL,?0);

????A(i);

????return?0;
}
其中上述中的主函數(shù)中的argc表示的是當(dāng)前輸入的參數(shù)個數(shù),而argv[1]表示的是輸入的第二個參數(shù),通過strtoul將字符串轉(zhuǎn)換為整型。下面是函數(shù)運(yùn)行的結(jié)果:

image-20210226162409999
通過上述可以看到運(yùn)行程序時輸入的命令是./exception3 2,那么這個時候也就是說argc的值等于2,而argv[0]的值等于./exception3(字符串),argv[1]的值等于2(字符)。

上述中,我們講述了異常處理機(jī)制時在扔出各個類型的異常時的處理方法,在整個C 教程中,貫穿始終的一直是這個概念,那么對于C 來說,拋出異常的時候可以拋出異常么,答案是可以的。下面我們就來看一個拋出異常的代碼,代碼如下所示,首先是類的代碼:

class?MyException
{

public:
????void?what(void)?{cout?<"This?is?MyException"?<endl;}
};
緊接著,我們來編寫各個函數(shù)的代碼:

void?C(int?i)
{
????int?a?=?1;
????double?b=?1.2;
????float?c?=?1.3;

????if?(i?==?0)
????{
????????cout<<"In?C,?it?is?OK"<<endl;
????}
????else?if?(i?==?1)
????????throw?a;
????else?if?(i?==?2)
????????throw?b;
????else?if?(i?==?3)
????????throw?c;
????else?if?(i?==?4)
????????throw?MyException();
}

void?B(int?i)
{
????cout<<"call?C?..."<<endl;
????C(i);
????cout<<"After?call?C"<<endl;
}

void?A(int?i)
{
????try?
????{
????????B(i);
????}?
????catch?(int?j)
????{
????????cout<<"catch?int?exception?"<endl;
????}?
????catch?(double?d)
????{
????????cout<<"catch?double?exception?"<endl;
????}?
????catch?(MyException?
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉