學(xué)習(xí)程序的好方法是閱讀代碼和改進(jìn)代碼。
下面的程例來自《An Overview of the C++ Programming Language》(5.1 異常和錯誤處理)
程序用途:使用C++的異常機(jī)制,報(bào)告stack的上溢或者下溢。(我適當(dāng)?shù)陌汛a補(bǔ)全。)
version 1 演示了基本的異常用法。
從try里拋出一個異常(實(shí)例或?qū)ο螅蒫atch里的類接受。
?1?version?1
?2?//?From:?An?Overview?of?the?C++?Programming?Language
?3??
?4?#include?<cstdlib>
?5?#include?<iostream>
?6?#include?<string>
?7?using?namespace?std;
?8?
?9?template<class?T>class?Stack{
10?????T*?v;
11?????int?max_size;
12?????int?top;
13?public:
14?????class?Underflow{?};???//?下溢
15?????class?Overflow{?};????//?上溢
16?????//?construct?function.?determine?the?size???
17?????Stack(int?s):?max_size(s),?top(0){?v?=?new?T[max_size];}??????
18?????~Stack(){}
19?????void?push(T?c){
20?????????if(top?==?max_size)?throw?Overflow();
21?????????v[top++]?=?c;
22?????}
23?????T?pop(){
24?????????if(top?==?0)?throw?Underflow();
25?????????return?v[--top];
26?????}
27?};?
28?
29?void?f()
30?{
31?????Stack<string>?ss(10);
32?????try{
33?????????ss.push("Quiz");
34?????????string?s?=?ss.pop();
35?????????ss.pop();
36?????}
37?????catch(Stack<string>::Overflow){
38?????????cerr?<<?"error:?stack?overflow"?<<?endl;
39?????}
40?????catch(Stack<string>::Underflow){
41?????????cerr?<<?"error:?stack?underflow"?<<?endl;
42?????}
43?}
44?
45?int?main(int?argc,?char?*argv[])
46?{
47?????f();
48?????system("PAUSE");
49?????return?EXIT_SUCCESS;
50?}
51?
52?輸出結(jié)果:error:?stack?underflow
53?
54?
改進(jìn),我們的第二個版本如下:
如果將
?1??class?Underflow{?};???//?下溢
?2?????class?Overflow{?};????//?上溢
?3?和
?4?????catch(Stack<string>::Overflow){
?5?????????cerr?<<?"error:?stack?overflow"?<<?endl;
?6?????}
?7?????catch(Stack<string>::Underflow){
?8?????????cerr?<<?"error:?stack?underflow"?<<?endl;
?9?????}
10?
分別改成如下:
?1?
?2?????class?Underflow{??????//
?3?????public:
?4?????????void?error(void){
?5?????????????cerr?<<?"stack?Underflow"?<<?endl;
?6?????????}????
?7?????};???
?8?????class?Overflow{???????//?
?9?????public:
10?????????void?error(void){
11?????????????cerr?<<?"stack?Overflow"?<<?endl;
12?????????}?
13?????};???
14?和
15?????catch(Stack<string>::Overflow&?e){
16?????????e.error();
17?????}
18?????catch(Stack<string>::Underflow&?e){
19?????????e.error();
20?????}
21?
改后的程序和原先的區(qū)別在哪里,看出來了嗎? 呵呵呵。
當(dāng)然,我們還能將代碼改進(jìn)。這樣產(chǎn)生了第三個版本。
第三個版本:version3
在Stack里面添加一個類class Stack_error,讓Underflow和Overflow都繼承它:
?1?
template<class?T>class?Stack{
?2?
????//?
????
?3?
public:
?4?
????class?stack_error{
?5?
????public:
?6?
????????virtual?void?error(void){ //當(dāng)然,可以把它做成純虛的。抽象類。
?7?
????????????cerr?<<?"stack_error"?<<?endl;
?8?
????????}
?9?
????};
10?
????class?Underflow:?public?stack_error{??????//
11?
????public:
12?
????????void?error(void){
13?
????????????cerr?<<?"stack?Underflow"?<<?endl;
14?
????????}????
15?
????};???
16?
????class?Overflow:?public?stack_error{???????//?
17?
????public:
18?
????????void?error(void){
19?
????????????cerr?<<?"stack?Overflow"?<<?endl;
20?
????????}?
21?
????};???
22?
????//?
23?
}
24?
接著把兩個catch合并成一個catch,如下。
??try{
?????//?the?same
????}
????catch(Stack<string>::stack_error&?e){
????????e.error();
????}
這三個版本的功能是一樣的,但版本越高,代碼越清晰,代碼也越容易維護(hù)。
如果我們設(shè)計(jì)了一個庫(比如上面的Stack),在開始的時候想到的就是兩個異常,overflow和underflow。如果有version1和version3 這兩種方法設(shè)計(jì)Stack,那么函數(shù)f()(用戶的代碼)也同樣version1和version3。當(dāng)一段日子過去了,我們準(zhǔn)備再加入一個異常,比如midflow()(呵呵呵,我也想不出有什么類似的異常了)。這樣的話,庫設(shè)計(jì)者對用戶說:“我們發(fā)現(xiàn)了midflow()異常,并加入庫代碼中,請您改寫您的代碼f()。”
這樣我們的version1得修改成如下形式:
void?f()
{
????Stack<string>?ss(10);
????try{
????//
.
????}
????catch(Stack<string>::Overflow){
????????cerr?<<?"error:?stack?overflow"?<<?endl;
????}
????catch(Stack<string>::Underflow){
????????cerr?<<?"error:?stack?underflow"?<<?endl;
????}
????catch(Stack<string>::Midflow){????//我們的找到所有撲捉stack異常的代碼,并加入這兩句。
??????????cerr?<<?"error:?stack?midflow"?<<?endl;
????}
}
而version3由于midflow()繼承了stack_error。而其接口還是一樣,客戶代碼就無需更改了。
?完畢。鞠躬。 請多多交流!
附:version3完整代碼:
?1?Version?3:
?2?#include?<cstdlib>
?3?#include?<iostream>
?4?
?5?using?namespace?std;
?6?
?7?template<class?T>class?Stack{
?8?????T*?v;
?9?????int?max_size;
10?????int?top;
11?public:
12?????class?stack_error{
13?????public:
14?????????virtual?void?error(void)?=?0;
15?????};
16?
17?????class?Underflow:?public?stack_error{??????//
18?????public:
19?????????void?error(void){
20?????????????cerr?<<?"stack?Underflow"?<<?endl;
21?????????}????
22?????};???
23?????class?Overflow:?public?stack_error{???????//?
24?????public:
25?????????void?error(void){
26?????????????cerr?<<?"stack?Overflow"?<<?endl;
27?????????}?
28?????};???
29?????Stack(int?s):?max_size(s),?top(0){?v?=?new?T[max_size];}????????//?construct?function.?determine?the?size???
30?????~Stack(){}
31?????void?push(T?c){
32?????????if(top?==?max_size)?throw?Overflow();
33?????????v[top++]?=?c;
34?????}
35?????T?pop(){
36?????????if(top?==?0)?throw?Underflow();
37?????????return?v[--top];
38?????}
39?};?
40?
41?void?f()
42?{
43?????Stack<string>?ss(0);
44?????try{
45?????????ss.push("Quiz");
46?????????string?s?=?ss.pop();
47?????????ss.pop();
48?????}
49?????catch(Stack<string>::stack_error&?e){
50?????????e.error();
51?????}
52?
53?}
54?
55?int?main(int?argc,?char?*argv[])
56?{
57?????f();
58?????system("PAUSE");
59?????return?EXIT_SUCCESS;
60?}
61?