C++异常处理涉及到三个关键字:try、catch、throw。
throw:用于抛出异常
catch:用于捕捉异常
try:块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个 catch 块。
如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。执行一个throw时,throw之后的语句将不再被执行(类似于return),程序会跳到与之匹配的catch模块。
代码示例:
int test(int a,int b)
{
if (b == 0)
{
throw "ERROR b = 0";
}
return(a/b);
}
int main()
{
int a = 0;
//test(4,0);不捕捉异常,直接运行,会出现段错误
try
{
a = test(4,0);
}
catch(const char* msg)
{
cout<<msg<<endl;
}
}
C++的标准异常:
异常 | 描述 |
---|---|
std::exception | 该异常是所有标准 C++ 异常的父类。 |
std::bad_alloc | 该异常可以通过 new 抛出。 |
std::bad_cast | 该异常可以通过 dynamic_cast 抛出。 |
std::bad_exception | 这在处理 C++ 程序中无法预期的异常时非常有用。 |
std::bad_typeid | 该异常可以通过 typeid 抛出。 |
std::logic_error | 理论上可以通过读取代码来检测到的异常。 |
std::domain_error | 当使用了一个无效的数学域时,会抛出该异常。 |
std::invalid_argument | 当使用了无效的参数时,会抛出该异常。 |
std::length_error | 当创建了太长的 std::string 时,会抛出该异常。 |
std::out_of_range | 该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator[]()。 |
std::runtime_error | 理论上不可以通过读取代码来检测到的异常。 |
std::overflow_error | 当发生数学上溢时,会抛出该异常。 |
std::range_error | 当尝试存储超出范围的值时,会抛出该异常。 |
std::underflow_error | 当发生数学下溢时,会抛出该异常。 |
示例代码:
int test(int a,int b)
{
if (b == 0)
{
throw std::bad_exception();
}
return(a/b);
}
int main()
{
int a = 0;
try
{
a = test(4,0);
}
catch(bad_exception)
{
cout<<"catch bad_exception"<<endl;
}
printf("1--------------\n");
try
{
a = test(4,0);
}
catch(...)//省略号表示捕捉任意类型的异常
{
cout<<"catch exception"<<endl;
}
printf("2--------------\n");
try
{
a = test(4,0);
}
catch(domain_error) //不会捕捉到这个异常
{
cout<<"domain_error"<<endl;
}
catch(bad_exception)
{
cout<<"catch bad_exception"<<endl;
}
printf("3--------------\n");
try
{
a = test(4,0);
}
catch(domain_error) //只捕捉domain_error类型的异常,与抛出的异常类型不一致,引发程序段错误
{
cout<<"domain_error"<<endl;
}
printf("4--------------\n");
}
catch语句是按照出现顺序逐一匹配的,越是专门的catch越应该置于catch列表的前端。因此当程序使用具有继承关系的多个异常时,必须对catch语句的顺序进行组织和管理,使得派生类的异常处理代码在基类异常处理代码之前。
我们可以通过继承和重载 exception 类来定义新的异常。下面的实例演示了如何使用 std::exception 类来实现自己的异常:
示例代码:
struct myException : public exception
{
const char * what () const throw ()
{
return "my exception";
}
};
int test(int a,int b)
{
if (b == 0)
{
throw bad_exception();
}
else if (b == 1)
{
throw myException();
}
return(a/b);
}
int main()
{
int a = 0;
try
{
a = test(4,1);
}
catch(myException &b)
{
cout<<"myException"<<endl;
cout<<b.what()<<endl; //把异常的信息打印出来
}
printf("1--------------\n");
try
{
a = test(4,0);
}
catch(bad_exception &b)
{
cout<<"bad_exception"<<endl;
cout<<b.what()<<endl; //把异常的信息打印出来
}
printf("2--------------\n");
}
what() 是异常类提供的一个公共方法,它已被所有子异常类重载。这将返回异常产生的原因。