码迷,mamicode.com
首页 > 编程语言 > 详细

第65课 C++中的异常处理(下)

时间:2016-07-08 23:22:44      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:

1. C++中的异常处理

(1)catch语句块可以抛出异常

  ①catch中获捕的异常可以被重新抛出

  ②抛出的异常需要外层的try-catch块来捕获

  ③catch(…)块中抛异常的方法是throw;也是将所有异常重新抛出

技术分享 

(2)catch块中重新抛异常的意义

  ①可以被外层try-catch块捕获,并重新解释异常的信息

  ②工程开发中使用这样的方式统一异常类型

    A.假设我们的私有库使用到了第3方的库函数,如func

    B.但其抛出的异常类型为int*类型,很不友好。我们可以在私有库使用func的地方捕获这个异常,并在catch块中重新解释这个异常并抛出为我们自定义的Exception类型.

技术分享 

【编程实验】异常的重新解释

#include <iostream>
using namespace std;

//演示在catch块中可以抛出异常
void Demo()
{
    try
    {
        try
        {
            throw c;
        }
        catch(int i)
        {
            cout << "Inner:catch(int i)" << endl;
            throw i;  //重新抛出异常
        }
        catch(...)
        {
            cout << "Inner:catch(...)" << endl;
            throw;  //抛出所有类型的异常
        }        
    }catch(...)
    {
        cout << "Outer:catch(...)" << endl;
    }
}

/*
    假设:当前的函数是第三方库中的函数。因此,我们无法修改源代码
    
    函数名: void func(int i)
    抛出异常的类型:int
                        -1 ==> 参数异常
                        -2 ==> 运行异常
                        -3 ==> 超时异常
*/
void func(int i)
{
    if ( i < 0 )
    {
        throw -1;
    }
    
    if ( i > 100 )
    {
        throw -2;
    }
    
    if ( i == 11)
    {
        throw -3;
    }
    
    //正常运时时
    cout << "Call func(int i)" << endl;
}


//以下是我们的私有库,当中使用到了第3方的库,这里需要将第3方库的
//异常类型统一成我们的异常信息格式
void MyFunc( int i)
{
    try
    {
        func(i);
    }
    catch(int i)
    {
        switch(i)
        {
        case -1:
            throw "Invalid Parameter";
            break;
        case -2:
            throw "Runtime Exception";
            break;
        case -3:
            throw "Timeout Exception";
            break;
        }
    }
}

int main()
{
    Demo();
    
    cout << endl;
    
    try
    {
        MyFunc(11);
    }
    catch(const char* cs)
    {
        cout << "Exception info: " << cs << endl; 
    }
    return 0;
};
/*输出结果:
Inner:catch(...)
Outer:catch(...)

Exception info: Timeout Exception
*/

2. 自定义异常类类型

(1)对于类类型异常的匹配依旧是至上而下严格匹配

(2)赋值兼容性原则在异常匹配中依然适用,因此一般而言:

  ①匹配子类异常的catch放在上部

  ②匹配父类异常的catch放在下部(否则如果放上面,则子类异常由于赋值兼容会被父类捕获)。

(3)工程中会定义一系列的异常类,每个类代表可能出现的一种异常类型。

(4)代码复用时可能需要重解释不同的异常类(如由于继承的层次关系,很可能父类的异常类在子类中会被重新解释)

(5)在定义catch语句块时推荐使用引用作为参数

【编程实验】类类型的异常

 

3.C++标准库中提供的异常类族

(1)标准库(#include <stdexcept>)中的异常都是从exception类派生的

(2)exception类有两个主要的分支

  ①logic_error:常用于程序中的可避免的逻辑错误

  ②runtime_error:常用于程序中无法避免的恶性错误

(3)标准库中的异常

技术分享 

【编程实验】标准库中的异常使用

 

4. C++异常机制中没提供finally块解决方案

(1)RAII技术(Resource Aquisition Is Initialization,资源获得即初始化)

  ①基本的思路:通过一个局部对象来表现资源,于是局部对象的析构函数将会释放资源。即,将资源封装成一个类,将资源的初始化封装在构造函数里,释放封装在析构函数里。要使用资源的时候,就实例化一个局部对象

  ②在抛出异常的时候,由于局部对象脱离了作用域自动调用析构函数,会保证资源被释放。

(2)具体做法

  ①直接使用局部变量。

try{
   File f("xxx.ttt"); //使用局部对象
   //其他操作
}  //异常发生时和正常情况下,文件资源都在这里被释放
catch {
    //...
}

  ②将资源封装在一个类中

class Test{
public:
    File *file;//资源被封装起来
    Test() { file = new file(...); }
    ~Test() { delete file;}
};

try{
   Test t; //使用局部对象
   //其他操作
}  //无论什么情况下,t在这里被释放,同时调用析构函数
catch {
    //...
}

  ③使用智能指针

try
{
    std::auto_ptr<file> pfile = new file();
    //....
}   //无论什么情况,智能指针都在这里被释放
catch(...)
{
    //....
}

5. 小结

(1)catch语句块中可以抛出异常

(2)异常的类型可以是自定义类类型

(3)赋值兼容性原则在异常匹配中依然适用

(4)标准库中的异常都是从exception类派生的。

第65课 C++中的异常处理(下)

标签:

原文地址:http://www.cnblogs.com/5iedu/p/5654806.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!