1. 程式人生 > >C++解析-外傳篇(2):函式的異常規格說明

C++解析-外傳篇(2):函式的異常規格說明

0.目錄

1.異常規格說明

2.unexpected() 函式

3.小結

1.異常規格說明

問題:
如何判斷一個函式是否會丟擲異常,以及丟擲哪些異常?

  • C++提供語法用於宣告函式所丟擲的異常
  • 異常宣告作為函式宣告的修飾符,寫在引數列表後面

異常規格說明的意義:

  • 提示函式呼叫者必須做好異常處理的準備
  • 提示函式的維護者不要丟擲其它異常
  • 異常規格說明是函式介面的一部分

問題:
如果丟擲的異常不在宣告列表中,會發生什麼?

下面的程式碼的輸出什麼?

示例——異常規格之外的異常:

#include <iostream>

using namespace std;

void func() throw(int)
{
    cout << "func()";
    cout << endl;
    
    throw 'c';
}

int main()
{
    try
    {
        func();
    }
    catch(int)
    {
        cout << "catch(int)";
        cout << endl;
    }
    catch(char)
    {
        cout << "catch(char)";
        cout << endl;
    }
    
    return 0;
}

執行結果為:

[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out 
func()
terminate called after throwing an instance of 'char'
Aborted (core dumped)

(不同編譯器執行結果不一樣。)

2.unexpected() 函式

  • 函式丟擲的異常不在規格說明中,全域性 unexpected() 被呼叫
  • 預設的 unexpected() 函式會呼叫全域性的 terminate() 函式
  • 可以自定義
    函式替換預設的 unexpected() 函式實現
  • 注意:不是所有的C++編譯器都支援這個標準行為

unexpected() 函式的替換:

  • 自定義一個無返回值無引數的函式
    1. 能夠再次丟擲異常
      1. 當異常符合觸發函式的異常規格說明時,恢復程式執行
      2. 否則,呼叫全域性 terminate() 函式結束程式
  • 呼叫 set_unexpected () 設定自定義的異常函式
    1. 引數型別為 void (*) ()
    2. 返回值為預設的 unexpected() 函式入口地址

示例1——自定義 unexpected() 函式:

#include <iostream>
#include <cstdlib>
#include <exception>

using namespace std;

void my_unexpected()
{
    cout << "void my_unexpected()" << endl;
    exit(1);
}

void func() throw(int)
{
    cout << "func()";
    cout << endl;
    
    throw 'c';
}

int main()
{
    set_unexpected(my_unexpected);
    
    try 
    {
        func();
    } 
    catch(int) 
    {
        cout << "catch(int)";
        cout << endl;
    } 
    catch(char) 
    {
        cout << "catch(char)";
        cout << endl;
    }
    
    return 0;
}

執行結果為:

[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out 
func()
void my_unexpected()

exit();改為throw 1;後的執行結果:
示例2——自定義 unexpected() 函式:

void my_unexpected()
{
    cout << "void my_unexpected()" << endl;
    // exit(1);
    throw 1;
}

執行結果為:

[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out 
func()
void my_unexpected()
catch(int)

(程式恢復執行了。)
(unexpected() 函式是正確處理異常的最後機會,如果沒有抓住這次機會,全域性的 terminate() 函式就會被呼叫,當前程式就只能以異常結束告終。)

3.小結

  • C++中的函式可以宣告異常規格說明
  • 異常規格說明可以看作介面的一部分
  • 函式丟擲的異常不在規格說明中,unexpected() 被呼叫
  • unexpected() 中能夠再次丟擲異常
    1. 異常能夠匹配,恢復程式的執行
    2. 否則,呼叫 terminate() 結束程式