当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

C++异常的基本语法与应用

    <异常处理>
    如果在程序的代码中出现了异常情况——也就是说,通过当前语境无法获得足够的信息以决定应该采取什么样的措施——程序员可以创建一个包含错误信息的对象并把它抛出当前语境,通过这种方式将错误信息发送到更大范围的语境中去。这种方式被称为“抛出一个异常”。
    try块
    如果在一个函数内部抛出了异常(或者被这个函数所调用的其他函数抛出了异常),这个函数就会因为抛出异常而退出。如果不想因为一个throw而退出函数,可以在函数中试图解决实际产生程序设计问题的地方(和可能产生异常的地方)设置一个try块。这个块被称做try块的原因是程序需要在这里尝试调用各种函数。try块只是一个普通的程序块,由关键字try引导:
try{
    //Code that may generate exceptions
}
    异常处理器
    异常处理器由多个catch函数块组成,catch函数块中的参数列表只能有一个参数,用于匹配由throw抛出的异常的类型,但是注意,最好是把catch函数块的参数写成引用传递,而不是值传递(因为这样可以避免将对象数据拆分和丢失的情况)。于是可以设置多个catch函数块,用于形成异常捕获网,捕获所以可能的异常类型。异常处理器紧接着try块,并且由关键字catch表示:

try{
    //Code that may generate exceptions
}catch(type1 id1){
  //Handle exceptions of type1
}catch(type2 id2){
  //Handle exceptions of type2
}catch(type3 id3){
  //Handle exceptions of type3
}
......
//Normal execution resumes heres...

    异常处理器都必须紧跟在try块之后。一旦某个异常被抛出,异常处理机制将会按照我们书写的catch块的代码顺序依次寻找匹配的异常处理器,一旦找到一个相匹配的异常处理器,则系统就可以认为该异常已经得到处理了。

以下是举例说明try块和catch块的用法:
#include<iostream>
using namespace std;
class Rainbow
{
public:
 Rainbow(){ cout<<\"Rainbow()\"<<endl;}
 ~Rainbow(){ cout<<\"~Rainbow()\"<<endl;}
};
void oz()
{
 Rainbow rb;
 for(int i =0;i<3;i++)
  cout<<\"There is no place like home.\\n\";
 throw 47;
}
int main(int argc, char ** argv)
{
 try
 {
  cout<<\"tornado, witch, munchkins ...\"<<endl;
  oz();
 }
 catch(int )
 {
  cout<<\"Auntie Em! I had the strangest dream...\"<<endl;
 } [Page]
 cout<<\"over\"<<endl;
 return 0;
}
//当执行函数oz()中的throw语句时,程序的控制流程开始回溯,直到找到某个具有int型的catch子句为止。程序在这个catch子句的主体中恢复运行。
//应当注意的是,当一个函数抛出一个throw异常时,如果该函数里面有构造了对象的话,系统会先对该对象调用析构函数,当对象调用完了析构函数以后,才开始执行异常的抛出工作!!!!!!

下面再看一个例子:

#include<iostream>
using namespace std;
class Except1 {};
class Except2 
{
public:
 Except2(const Except1&) {} //以Except1来拷贝构造函数Except2。可以~
};
void f() { throw Except1();} //抛出Except1类型的异常,即使没有构造,但是可以使用系统自己生成                            //的默认的构造函数。
int main()
{
 try{
  f();
 }
 catch(Except2&)  //强调过了catch语句最好用的是引用传递而不是值传递。
 {
  cout<<\"inside catch(Except2&)\"<<endl;
 }
 catch(Except1&)
 {
  cout<<\"inside catch(Except1&)\"<<endl;
 }
 return 0;
}
//尽管读者可能会认为,通过使用转换构造函数将一个Except1对象转换成一个Except2对象,可以使得第一个异常处理器被匹配。但是,异常处理系统在处理异常的过程中不做这种这种转换,它只寻找和它最配的进行处理,所以异常将被第二个catch语句捕获。

对于有继承关系的类的异常的处理时,有这么一条原则:就是在异常的处理器catch捕获语句中,基类的类型总是可以包含本身甚至其派生类的类型,而派生类只能自己指明自己的类型,不能向上兼容,而基类则可以向下兼容。所以在对继承类的对象的捕获的过程中,为了避免基类垄断的局面,则将catch语句的排布从上到下为派生类到基类的顺序编写。这样可以保证派生类先找到属于自己的异常处理器,而最后再由基类找自己的类型。
举例:
#include<iostream>
using namespace std;
class X
{
public:
 class Trouble {};   //注意:类中嵌套类的申明和定义,学习!!!
 class small: public Trouble {};
 class big:public Trouble {};//类中的继承!!!

共4页 首页 上一页 1 2 3 4 下一页 尾页 跳转到
相关内容
赞助商链接