c++ 异常
try...catch 中,控制权如何从 try块 转移到 catch块?
1.使用 throw 表达式将临时对象 temp 初始化为 Exception Type temp {theException};
2.在 try 块中定义的所有自动对象调用析构函数【将在try中声明的局部变量释放掉】
3.选择参数类型与异常类型匹配的第一个处理程序
4.使用异常的副本把参数初始化为 typeN ex(temp);并把控制权传递给处理程序
5.除非处理程序中的代码决定结束程序,否则在处理程序执行完之后,将继续执行 try 块的最后一个处理程序后面的语句。
异常处理流程【程序中的 try...catch 必须是仅挨着的,类比 if...else... 】
try { /*code that may throw exceptions*/ } catch (parameter specifying exception type 1) { /*handle the exception*/ } catch (parameter specifying exception type 2) { /*handle the exception*/ } catch (parameter specifying exception type 3) { /*handle the exception*/ }
try 中 throw 不同类型的 exception 对应后边不同的 catch,catch 相同类型的 exception 时只匹配最前边的。
int main() { try { if (0) throw 1; if (0) throw "test"; if (1) throw 1.0; } catch (int i) { std::cout << 4 << std::endl; return -1; } catch (const char* message) { std::cout << 5 << std::endl; return -1; } catch (double x) { std::cout << 6 << std::endl; return -1; } std::cout << "test" << std::endl; return 0; }
当上边的 catch 匹配上之后,如果不 return ,下边的 catch 同样不会执行,但是 catch 之后的语句会正常执行。
try块的嵌套
int main() { try { try { throw "test"; } catch(int i) { std::cout << 1 << std::endl; } } catch(const char* message) { std::cout << 2 << std::endl; } return 0; }
catch中的变量何时调用析构函数
class Trouble { private : std::string message; public : Trouble(std::string str = "there's a problem") : message {str} {std::cout << "constructor" << std::endl;} ~Trouble() {std::cout << "destructor" << std::endl;} std::string what() const {return message;} }; int main() { try { throw Trouble{}; } #if 0 //case 0 catch (const Trouble t) { #else //case 1 catch (const Trouble& t) { #endif std::cout << t.what() << std::endl; } return 0; }
case 0:
$ ./exceptions
constructor
there's a problem
destructor //复制的对象,不需要调用构造函数,多调用了一次析构函数
destructor
case 1:
$ ./exceptions
constructor
there's a problem
destructor
【相当于是传递参数,如果传递的参数是引用则不需要重新创建,参见 本博客:c++构造函数和析构函数 第三个demo】
抛出异常的函数,不抛出异常的函数
//不会将所有异常全部catch掉
void doThat(int argument) try { //code for the funticon } catch () { //Handler code for the exceptions }
//能够catch所有异常,不让异常抛出 void doThar(int argument) noexcept try { //code for the funticon } catch () { //Handler code for the exceptions }
标准库异常
/*未完待续*/