c++有一些在現實世界中很少看到的結構。這些結構有着自己的用法,但是要特別小心保守的予以運用。就像是網站 The Old New Thing首頁標題上面的說的那樣:
“代碼通常被讀的次數原因超過了被寫的次數,所以計划要遵循此道。”
在下面將介紹一些很少有人能夠知道的c++構造函數,包括其中的運用場景,語法和陷阱。
運用場景
try函數塊的應用場景一般局限於下面幾個:
(1)構造函數初始化列表;
(2)基類構造含數據;
(3)析構函數;
語法
對於函數
void f() try { /*...*/ } catch (...) { /*...*/ }
這等價於
void f() { try { /*...*/ } catch (...) { /*...*/ } }
對於構造函數初始化列表
struct A : public B { A() try : B(), foo(1), bar(2) { // constructor body } catch (...) { // exceptions from the initializer list are caught here // but also rethrown after this block (unless the program is aborted) } private: Foo foo; Bar bar; };
對於析構函數來說,跟正常函數的使用方法是類似的
struct A { ~A() try { // destructor body } catch (...) { // exceptions from the destructor are caught here // but also rethrown after this block (unless the program is aborted) } };
陷阱
- 任何在構造函數和析構函數中捕捉的異常,默認情況下都會被重新拋出。這樣的話,大多是情況下當捕捉到一個異常的時候,你能夠做的事情就是用日志記錄,或者是做一些清理工作。不管一個對象因為什么原因而失敗了,你都不應該嘗試去保存它的實例。
- 在函數catch塊中的return語句表現的跟函數中的返回語句一樣;
- 但控制流走到catch模塊最后的時候,函數將返回。如果沒有任何返回語句而且函數返回類型是非void的,那么行為將會是不確定的。
- try塊函數主要有一些非直觀的行為:
- 從命名空間范圍內定義的構造函數中拋出的異常無法捕捉。
- 從static變量中獲取的析構函數的對象中拋出的異常無法捕捉。
如上,try模塊函數在進行代碼審查的時候至少是應該引起重視的。try塊函數使用並非都是錯的,在一些上沒有提到的用戶場景中用到的時候,很容易出現問題。
來源http://szelei.me/rarely-known-cpp-constructs-part-1-function-try-blocks/