异常处理是程序用来处理运行时错误的一种结构化方法。C++ 的异常处理机制建立在 3 个关键字上:try, catch 和 throw 。一般情况是:
在 try 代码块中包含你想要监控的程序部分。如果 try 中的程序发生了一个异常,那么这个异常将被抛出( throw ),然后我们使用 catch 来捕获并处理这个异常。通用形式如下:
[C++] 纯文本查看 复制代码
try {
// try 代码块
}
catch (type1 arg) {
//catch 代码块
}
catch (type2 arg) {
//catch 代码块
}
...
catch (typeN arg) {
//catch 代码块
}
try 中必须包含想要监控的程序段,这个程序段可能是一个函数中的几条语句,也可以是整个 main() 函数(这样整个程序都将被监控)。
当 try 中的程序抛出一个异常时,它将被相应的 catch 语句捕获并处理。catch 语句可以有多个,每个语句中指定某个与异常匹配的类型,一旦发生匹配,那么这个 catch 语句将被执行,而所有其他的 catch 语句都会被忽略。当异常被捕获时,变量 arg 用来接收异常的值。程序可以捕获任意类型的数据,也包括自己创建的类型。
throw 语句的通用形式如下:throw 语句生成由 exception 指定的异常,如果要抛出这个异常,则 throw 就要放在 try 中,或者 try 中代码所调用的函数中(直接或间接)。
下面是一个简单的示例程序,演示了异常处理过程:
[C++] 纯文本查看 复制代码 #include <iostream>
using namespace std;
int main()
{
cout << "start\n";
try { //try 程序块
cout << "Inside try block\n";
throw 99; //抛出异常
cout << "This will not execute";
}
catch (int i) { //捕获异常
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "end\n";
return 0;
}
运行输出:start
Inside try block
Caught an exception -- value is: 99
end 由程序的输出可见,当 try 中抛出异常后,程序的执行流程转移到 catch 语句,try 同时结束。也就是说,catch 语句不是被调用,而是程序的执行流程转移到了 catch 语句中。这样,throw 语句后面的 cout 语句就永远得不到执行。在执行完 catch 语句后,程序的流程是继续执行 catch 后面的语句。
注意:如果抛出的异常没有与之相配的 catch 语句,那么将发生非常长的程序终止。如果程序抛出了一个未被处理的异常,系统将调用 C++ 标准库中 的函数 terminate() 。默认情况下,terminate() 会调用函数 abort() 来终止程序,如果愿意,你也可以自定义一个程序终止处理函数。
比如在上面的程序中,如果 catch 语句中的异常类型改为 double,那么抛出的异常将不会被捕获,从而产生非正常的程序终止,如下所示:
[C++] 纯文本查看 复制代码 #include <iostream>
using namespace std;
int main()
{
cout << "start\n";
try { //try 程序块
cout << "Inside try block\n";
throw 99; //抛出异常
cout << "This will not execute";
}
catch (double i) { //捕获异常
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "end\n";
return 0;
}
运行输出(G++ 编译器,编译器不同输出的信息也可能不同):start
Inside try block
terminate called after throwing an instance of 'int'
Aborted
在 try 中调用的函数所抛出的异常也可以被该 try 块捕获,比如:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
void Xtest(int test)
{
cout << "Inside Xtest, test is: " << test << "\n";
if(test) throw test;
}
int main()
{
cout << "start\n";
try { //try 块
cout << "Inside try block\n";
Xtest(0); //try 块中的 Xtest() 函数抛出的异常也能被捕获
Xtest(1);
Xtest(2);
}
catch (int i) { //捕获异常
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "end";
return 0;
}
运行输出:
[C++] 纯文本查看 复制代码 start
Inside try block
Inside Xtest, test is: 0
Inside Xtest, test is: 1
Caught an exception -- value is: 1
try 也可以用在函数中。在这种情况下,每次程序执行该函数时,与函数相关的异常处理将被复位,如下所示:
[C++] 纯文本查看 复制代码 #include <iostream>
using namespace std;
void Xhandler(int test)
{
try {
if (test) throw test;
}
catch (int i) {
cout << "Caught One. Ex. #: " << i << '\n';
}
cout << "function end.\n";
}
int main()
{
cout << "start\n";
Xhandler(1);
Xhandler(2);
Xhandler(0);
Xhandler(3);
cout << "end\n";
return 0;
}
运行输出:start
Caught One. Ex. #: 1
function end.
Caught One. Ex. #: 2
function end.
function end.
Caught One. Ex. #: 3
function end.
end 从输出结果中可见,程序中共抛出 3 个异常,在每次抛出异常后,函数将返回。当函数再次被调用时,异常处理也将被复位 |