C++异常的主要目的是为了设计容错程序提供语言级支持。
即异常使得在程序设计中包含错误处理功能更加容易,以免事后采取一些严格的错误处理方式。
异常的灵活性和相对方便性激励着程序员在条件允许的情况下在程序设计中加入错误处理功能。
总之,异常是这样一种特性,类似于类,可以改变你的编程方式。
较新的C++编译器将异常合并到语言中。
exception头文件定义了exception类。C++可以把它用作其他异常类的基类。
代码可以引发exception异常,也可以将exception用作基类
有一个名为what()的虚函数,它返回一个字符串,该字符串的特征随实现而异。
而且what()函数是一个虚方法,所以可以在基类当中重新定义它。
1 #include <iostream> 2 class bad_hmean:public std::exception 3 { 4 public: 5 const char * what() {return "bad arguments to hmean()";} 6 ... 7 }; 8 class bad_gmean:public std::exception 9 { 10 public: 11 const char * what() {return "bad arguments to gmean()";} 12 ... 13 }; 14 15 try{ 16 ... 17 } 18 catch(std::exception & e) 19 { 20 cout<<e.what()<<endl; 21 ... 22 }
如果不想以不同的方式处理这些派生而来的异常,可以在同一个基类处理程序中捕获它们。
否则,可以分别捕获它们;
C++定义了很多基于exception类的异常;
1、stdexcept头文件的异常类
头文件stdexcept定义了其他几个异常类。首先,该文件定义了logic_error和runtime_error类。
它们都是以公有方式从exception派生而来的。
一般而言,logic_error系列异常表明存在可以通过编程修复的问题;
runtime_error系列异常表明存在无法避免的问题;
所有这些错误类有相同的常规特征,它们之间的主要区别在于:不同类名让您能够分别处理每种异常。
另一方面,继承关系能够让您一起处理它们(如果你愿意的话)。
2.bad_alloc异常和new
对于使用new导致的内存分配问题,C++最新的处理方式是让new引发bad_alloc异常。
头文件new包含bad_alloc类的声明,它是exception类公有派生而来的。
但在以前,当无法分配请求的内存量时,new返回一个空指针。
1 // newexcp.cpp -- the bad_alloc exception 2 #include <iostream> 3 #include <new> 4 #include <cstdlib> 5 using namespace std; 6 7 struct Big 8 { 9 double stuff[20000]; 10 }; 11 12 int main() 13 { 14 Big * pb; 15 try { 16 cout<<"Trying to get a big block of memory: "; 17 pb = new Big[10000]; 18 cout<<"Got past the new request: "; 19 } 20 catch(bad_alloc & ba) 21 { 22 cout<<"Caught the exception! "; 23 cout<<"ba.what()"<<endl; 24 exit(EXIT_FAILURE); 25 } 26 cout<<"Memory successfully allocated "; 27 pb[0].stuff[0]=4; 28 cout<<pb[0].stuff[0] <<endl; 29 delete [] pb; 30 return 0; 31 }
3.空指针和new
很多代码都是在new失败时返回空指针时编写的。
为处理new的变化,有些编译器提供了一个标记(开关),让用户选择所需的行为。
当前,C++标准提供了一种在失败时返回空指针的new,其用法如下
int * pi = new (std::nothrow) int;
int * pa = new (std::nowthrow) int[500];
使用这种new,可将上面程序的核心代码修改如下:
Big * pb;
pb = new(std::nothrow) Big [10000];
if(pb ==0)
{
cout<<"Could not allocate memory. Bye. ";
exit(EXIT_FAILURE);
}