C++異常處理機制的弊端
C++是C語言的升級版,引入了很多高級語言特性,其中就包括異常處理機制。
跟其他語言類似,C++使用try catch throw關鍵字處理異常。一個簡單的C++異常處理程序,類似這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <iostream> using namespace std;
double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); }
int main () { int x = 50; int y = 0; double z = 0; try { z = division(x, y); cout << z << endl; } catch (const char* msg) { cerr << msg << endl; }
return 0; }
|
看起來非常不錯,異常被捕獲了。編譯運行該程序
1
| Division by zero condition!
|
盡管預定義了很多標準異常,但是,現實中面對復雜業務場景,異常處理變得很蹩腳。
先看下面這個我根據真實的案例模擬的小程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <iostream> #include <exception> using namespace std;
struct MyException : public exception { const char * what () const throw () { return "C++ Exception"; } }; struct MyException2 : public exception { const char * what () const throw () { return "C++ Exception2"; } }; struct MyException3 : public exception { const char * what () const throw () { return "C++ Exception3"; } };
void efun1() { throw MyException(); }
void efun2() { throw MyException2(); } void efun3() { try{ efun1(); efun2(); }catch(...) { throw MyException3(); } }
void efun() { try { efun3(); }catch(...) { throw; } } int main() { try { efun(); } catch(std::exception& e) { //Other errors std::cout << "Std Exception caught" << std::endl; std::cout << e.what() << std::endl; } }
|
其中,efun3 調用efun1,efun2 會拋出MyException3(). 那么main調用efun3所捕獲的異常將是MyException3(), 而不是efun1異常MyException1()。 也就是說,MyException1被MyException3覆蓋了。
你可能會說,efun3 不應該拋出自己的異常,只需要catch什么就throw什么。 這當然可以解決部分問題。但現實的場景往往是復雜的,
1 2 3 4 5 6 7 8 9
| void efun3() { efun1(); //some IO operation efun2() //memory allocation.. ... //call 3rd-party api }
|
可見,為了完美捕獲異常,代碼作者需要非常小心,而且可讀性變差。而維護代碼的代價也是不小。所以,干脆不要使用異常處理。
C++不使用異常處理
因為已經有谷歌背書,所以我說話的底氣也足了。谷歌C++代碼規范
關于構造函數異常的處理,并不是問題。你沒必要非得在構造函數里面干那些拋異常的事情。
當然沒了異常處理,你的log 和 error code也需要好好設計才是。
AD