1、概念
异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接
的调用者处理这个错误。
throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
catch: 在您想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常,可以有多
个catch进行捕获。
try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。
先简单展示一个代码
double Division(int a, int b)
{
// 当b == 0时抛出异常
if (b == 0)
throw "Division by zero condition!";//当throw 回去的是字符串,catch就要接受字符串
if (b == 0)
throw b;//当throw 回去的是int,catch要用 int& 接收
else
return ((double)a / (double)b);
}
void Func()
{
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
int main()
{
try
{
Func();
}
catch (int &b)//当不需要b的值时,可以缺省 catch (int)
{
cout << "b==0" << endl;
}
catch (const char* errmsg)
{
cout << errmsg << endl;
}
catch (...)//匹配所有
{
cout << "unkown exception" << endl;
}
return 0;
}
2、异常的各种处理
异常的抛出和匹配原则
1、 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。
2、被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3、 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成
一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似于函数的传值返回)
4、 catch(…)可以捕获任意类型的异常,问题是不知道异常错误是什么。
5、 实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象,使用基类捕
获。
2.1异常的重新抛出
有可能嵌套的抛出异常,单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用链函数来处
理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。
double Division(int a, int b)
{
// 当b == 0时抛出异常
if (b == 0)
{
throw "Division by zero condition!";
}
return (double)a / (double)b;
}
void Func()
{
// 这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放。
// 所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再
// 重新抛出去。
int* array = new int[10];
try {
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
catch (...)
{
cout << "delete1 []" << array << endl;
delete[] array;
throw;
}
cout << "delete2 []" << array << endl;
delete[] array;
}
int main()
{
try
{
Func();
}
catch (const char* errmsg)
{
cout << errmsg << endl;
}
return 0;
}
2.2 基类捕获父类
基类抛出异常, throw SqlException();,可以使用父类来捕获 catch ( Exception& e)。
class Exception
{
public:
virtual void What()
{
cout << "Have a Exception" << endl;
}
};
class SqlException : public Exception
{};
class CacheException : public Exception
{};
class HttpServerException : public Exception
{};
void Start()
{
throw SqlException(); // 抛出对象都是子类对象
}
int main()
{
try {
Start();
}
catch ( Exception& e) // 这里捕获父类对象就可以
{
e.What();
}
catch (...)
{
cout << "Unkown Exception" << endl;
}
return 0;
}
2.3 多态
利用虚函数可以对代码进行多态,throw子类,catch父类,返回指定子类的错误。
class Exception //父类
{
public:
virtual void What() = 0;
public:
string _errmsg = "Have a Exception.";
};
class SqlException : public Exception
{
public:
virtual void What()
{
cout << "SqlException Exception" << endl;
}
};
class CacheException : public Exception
{
public:
virtual void What()
{
cout << "CacheException Exception" << endl;
}
};
class HttpServerException : public Exception
{
public:
virtual void What()
{
cout << "HttpServerException Exception" << endl;
}
};
void Startup()
{
//throw SqlException();
throw HttpServerException();
}
int main()
{
try
{
Startup();
}
catch (Exception& e)
{
e.What(); //多态
}
catch (...)
{
cout << "Unkown Exception" << endl;
}
return 0;
}
输出: HttpServerException Exception