適合具備 C 語言基礎(chǔ)的 C 教程(十二)
時間:2021-08-19 15:49:33
手機(jī)看文章
掃描二維碼
隨時隨地手機(jī)看文章
[導(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
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()
中存在問題,那么就捕獲這個錯誤,這里的catch
和C()
函數(shù)里的throw 1
是所對應(yīng)起來的。程序運(yùn)行結(jié)果如下所示:也就說,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é)果:通過上述可以看到運(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?