【C/C++】C++异常基础知识点
1. 何为出错处理(Exception handling):
在编程过程中,很多时候我们是无法确定一段代码是否总是能够正常工作的,或者因为程序访问了并不存在的资源,或者由于一些变量超出了预期的范围,等等。
这些情况我们统称为出错(例外),C++ 新近引入try, throw, catich来帮助处理这种出错情况。
2. try-throw-catch基本用法:
try {
// code to be tried
throw exception;
}
catch (type exception)
{
// code to be executed in case of exception
}
这三个关键字所做的操作是:try 语句块中的代码被正常执行。如果有例外发生,代码必须使用关键字throw 和一个参数来扔出一个例外。这个参数可以是任何有效的数据类型,它的类型反映了例外的特征。如果有例外发生,也就是说在try 语句块中有一个throw 指令被执行了,则catch 语句块会被执行,用来接收throw传来的例外参数。
举例:
#include <iostream.h>
int main () {
char myarray[10];
try {
for (int n=0; n<=10; n++) {
if (n>9) throw "Out of range";
myarray[n]='z';
}
} catch (char * str) {
cout << "Exception: " << str << endl;
}
return 0;
}
执行结果为:Exception: Out of rang
throw 语法与 return 相似,只是参数不需要扩在括号。catch 语句块必须紧跟着try 语句块后面,中间不能有其它的代码。catch 捕获的参数可以是任何有效的数据类型。catch 甚至可以被重载以便能够接受不同类型的参数。在这种情况下被执行catch 语句块是相应的符合被throw扔出的参数类型的那一个:
#include <iostream.h>
int main () {
try {
char * mystring;
mystring = new char [10];
if (mystring == NULL) throw "Allocation failure";
for (int n=0; n<=100; n++) {
if (n>9) throw n;
mystring[n]='z';
}
} catch (int i) {
cout << "Exception: ";
cout << "index " << i << " is out of range" << endl;
} catch (char * str) {
cout << "Exception: " << str << endl;
}
return 0;
}
执行结果为:Exception: index 10 is out of range
我们还可以定义一个catch 语句块来捕获所有的例外,不论扔出的是什么类型的参数。这种情况我们需要在catch 或面的括号中写三个点来代替原来的参数类型和名称,如:
try {
// code here
}
catch (...) {
cout << "Exception occurred";
}
try-catch 也是可以被嵌套使用的。在这种情况下,我们可以使用表达式throw;(不带参数)将里面的catch 语句块捕获的例外传递到外面一层,例如:
try {
try {
// code here
}
catch (int n) {
throw;
}
}
catch (...) {
cout << "Exception occurred";
}
3. 没有捕获的例外 (Exceptions not caught):
如果由于没有对应的类型,一个例外没有被任何catch 语句捕获,一个默认的特殊函数terminate 将被调用。
这个函数通常已被定义了,以便立即结束当前的进程(process),并显示一个“非正常结束”( "Abnormal termination")的出错信息。它的格式是:
void terminate();
4. 标准例外 (Standard exceptions):
一些C++ 标准语言库中的函数也会扔出一些列外,我们可以用try 语句来捕获它们。这些例外扔出的参数都是std::exception 引申出的子类类型的。这个类(std::exception) 被定义在C++ 标准头文件 中,用来作为exceptions标准结构的模型:
因为这是一个类结构,如果你包括了一个catch 语句块使用地址(reference)来捕获这个结构中的任意一种列外 (也就是说在类型后面加地址符 &),你同时可以捕获所有引申类的例外 (C++的继承原则)。
下面的例子中,一个类型为 bad_typeid 的例外(exception的引申类),在要求类型信息的对象为一个空指针的时候被捕获:
#include <iostream.h>
#include <exception>
#include <typeinfo>
class A {virtual void f() {}; };
int main () {
try {
A * a = NULL;
typeid (*a);
} catch (std::exception& e) {
cout << "Exception: " << e.what();
}
return 0;
}
执行结果为:Exception: Attempted typeid of NULL pointer
你可以用这个标准的例外层次结构来定义的你的例外或从它们引申出新的例外类型。