#include <iostream>
using namespace std;
int divide(int a,int b){
if(b)
return a/b;
else
throw "b can't zero.";
}
int main(){
int a,b;
cin >> a >> b;
try{
cout << divide(a,b) << endl;
}
catch(const char *s){
cout << s << endl;
}
return 0;
}
如果异常没有catch住的话,最终会导致程序调用abort(),异常终止。
如果异常不是本函数产生的话,可以再将异常抛出。在这个例子中print可以没有catch。
#include <iostream>
using namespace std;
int divide(int a,int b){
if(b)
return a/b;
else
throw "b can't zero.";
}
void print(int result)
{
try{
cout << result << endl;
}
catch(const char *s){
throw;
}
}
int main(){
int a,b;
cin >> a >> b;
try{
print(divide(a,b));
}
catch(const char *s){
cout << s << endl;
}
return 0;
}
引发异常时,编译器总会自动创建一个临时拷贝,即使异常catch块中指定的是引用。因为f()异常,导致桟解退,a已经被析构了。
class problem{//...};
void f()
{
if(//...){
problem a;
thow a;
}
//...
}
int main()
{
try{
f();
}
catch(problem &b){
//.....
}
return 0;
}
可以利用类的关系来接异常
class bad_1{};
class bad_2:public bad_1{};
class bad_3:public bad_2{};
void f()
{
if()
throw bad_1();
else if()
throw bad_2();
else if()
throw bad_3();
//....
}
int main(){
try{
f();
}
catch(bad_3 &a){
}
catch(bad_2 &b){
}
catch(bad_3 &c){
}
}
如果不知道异常的类型,可以用cathc(...){}
来接住任何异常。
异常规范和C++
void f() throw(int,double){}
这是C++98的新特性,但是C++11却摒弃了,不过还是支持它。表明f()可能会抛出int和double的异常,并保证该函数不会抛出任何其他类型的异常。让编译器添加执行运行阶段检查的代码,检查是否违背了异常规范。如果在运行时,函数抛出了一个没有被列在它的异常规范中的异常时(并且函数中所抛出的异常,没有在该函数内部处理)则系统调用C++标准库中定义的函数unexpected()。仅当函数中所抛出的异常,没有在该函数内部处理,而是逆调用链回溯寻找匹配的catch子句的时候,异常规范才起作用。如果异常规范形式为throw(),则表示不得抛出任何异常。
void f() noexcept;//表明f()不会引发任何异常
桟解退(unwinding the stack)
exception类
异常的基类
//c++11
class exception {
public:
exception () noexcept;
exception (const exception&) noexcept;
exception& operator= (const exception&) noexcept;
virtual ~exception();
virtual const char* what() const noexcept;
}
C++ 提供了一系列标准的异常,定义在
下表是对上面层次结构中出现的每个异常的说明:
异常终止函数设置
当异常没有接住时,程序自动调用terminate
函数,而terminate
默认调用abort
函数,可以通过set_terminate
来修改这个默认值。
typedef void (*terminate_handler)();
terminate_handler set_terminate(terminate_handler f) noexcept//c++11
void terminater() noexcept;
如果在异常规范中引发了规范中没有的异常,程序将调用unexpected
函数,unexpected
默认调用terminate
,并最总导致abort
函数的调用。可以通过set_unexpected
来修改这个默认值。
typedef void (*unexpected_handler)();
unexpected_handler set_unexpected(unexpected_handler f) noexcept//c++11
void set_unexpected() noexcept;