C++指针对象和异常(12)

异常(exception)

为什么有异常

异常在C++用于错误处理,C语言中一般使用返回值表示错误,C++对错误处理进行了扩展,统一使用异常机制来处理程序中发生的错误。

C++的异常处理包括两个部分 ----- 抛出异常和捕获异常,如果抛出的异常被捕获,处理完之后程序会继续运行,如果抛出的异常未被捕获,将导致程序终止。

异常的抛出和捕获

异常抛出 ------- throw

throw是用于抛出异常的关键字,用法如下:

throw 异常(对象);

在函数声明中应该指定可能抛出的异常,应该在函数声明指定。

void show();//该函数可能抛出任何异常 void show()throw();//该函数不抛出任何异常 void show()throw(char,int);//该函数可能抛出char和int型异常

/*03-异常的抛出和捕获*/
#include 
#include 
#include 

using namespace std;

class A {
public:
    //不抛出任何异常
    void show()throw()
    {
        cout << "show A" << endl;
    }
};

//foo函数可能抛出int,double,const char *,A *类型的异常
void foo()throw(int, double, const char*)
{
    srand(time(0));
    int s = rand() % 4;//0 1 2 3 4

    cout << "foo start!" << endl;

    if (s == 0) {
        cout << "正常运行!" << endl;
    }
    else if (s == 1) {
        //抛出int型异常
        throw 1;
    }
    else if (s == 2) {
        //抛出double型异常
        throw 3.14;
    }
    else if (s == 3) {
        //排除const char *型异常
        throw "起火了";
    }
    cout << "foo finished!" << endl;
}

int main()
{
        foo();
        cout << "after foo!" << endl;
  
    //vs会报错,抛出后没有处理
    cout << "app finished!" << endl;
    return 0;
}

异常的捕获 ---------- try…catch

捕获异常使用try…catch关键字,用法如下:

try{ //可能抛出异常的代码 }catch(异常类型1 变量){//根据类型捕获异常 //处理异常类型1的代码 }catch(异常类型2 变量){//根据类型捕获异常 //处理异常类型2的代码 //throw 变量 ----- 继续向上一层抛出 }… //… //异常被捕获后,执行对应的异常处理代码,然后继续执行try…catch之后的代码 //异常未被捕获,仍然导致程序终止 //捕获异常后,如果当前无法处理,可以继续抛出

/*03-异常的抛出和捕获*/
#include 
#include 
#include 

using namespace std;

class A {
public:
    //不抛出任何异常
    void show()throw()
    {
        cout << "show A" << endl;
    }
};

//foo函数可能抛出int,double,const char *,A *类型的异常
void foo()throw(int, double, const char*, A*)
{
    srand(time(0));
    int s = rand() % 5;//0 1 2 3 4

    cout << "foo start!" << endl;

    if (s == 0) {
        cout << "正常运行!" << endl;
    }
    else if (s == 1) {
        //抛出int型异常
        throw 1;
    }
    else if (s == 2) {
        //抛出double型异常
        throw 3.14;
    }
    else if (s == 3) {
        //排除const char *型异常
        throw "起火了";
    }
    else if (s == 4) {
        //排除A *型异常
        throw new A;
    }

    cout << "foo finished!" << endl;
}

int main()
{
    try {
        foo();
        cout << "after foo!" << endl;
    }
    catch (int e) {//捕获int异常
        cout << "捕获到了int型异常=" << e << endl;
    }
    catch (double e) {//捕获double异常
        cout << "捕获到了double型异常=" << e << endl;
    }
    catch (const char* e) {//捕获const char *异常
        cout << "捕获到了const char *型异常=" << e << endl;
        cout << "无法处理,继续抛出" << endl;
        throw e;
    }
    catch (A* e) {//捕获A *异常
        cout << "捕获到了A *型异常" << endl;
        e->show();
        delete e;
    }

    cout << "app finished!" << endl;
    return 0;
}

练习:

实现捕获A *类型的异常,同时调用该异常的show函数。

异常的层次设计

C++指针对象和异常(12)_第1张图片

异常处理的原则是分层次捕获和处理,捕获到了本层的异常就直接处理返回 捕获到了不属于本层的异常就继续抛出

系统预定义异常

C++中预定义类一些异常,为C++预定义的类和函数(string cin cout new…)服务,在编程中可以直接使用。

预定义的异常类都是exception的子类/间接子类,当调用C++预定义类中的成员函数和预定义的全局函数时,可能抛出这些异常。

C++指针对象和异常(12)_第2张图片

使用C++预定义异常需要包含头文件

 #include               

exception类中有一个虚函数 ----- what(),该函数返回异常原因的字符串

用户自定义异常

在C++项目开发中,详细设计时应该设计好异常的框架,通常的做法就是定义一个异常的基类,项目中所有的异常都是该类的子类/间接子类。

在代码中根据条件抛出异常

在函数语句中抛出

在执行可能排除异常的代码时捕获异常

try{ //… }catch(…){ //… }… //根据不同的异常进行不同的处理

注意:如果代码可能抛出的异常中有多态性的父子关系,捕获异常时必须先捕获子类异常,再捕获父类异常。

练习:

1.为MyArray类添加一个at成员函数,该函数可能抛出out_of_range的异常;

int &at(size_t n) { }

构造函数可能抛出bad_alloc异常。

在使用该类的代码中捕获这些异常。

作业:

1.扩展自定义异常的代码(dms_exception)

添加 服务器无响应的异常子类/服务器资源不足异常子类 继承 服务器异常类 添加 客户端网络无连接的异常子类/客户端发送数据越界异常子类 继承 客户端异常类

在send_data函数函数抛出这些异常,在主函数中捕获。 C++指针对象和异常(12)_第3张图片

/*dms_exception.h*/
#ifndef DMS_EXCEPTION_H
#define DMS_EXCEPTION_H

#include 
using namespace std;

//异常的基类
class dms_exception {
public:
    dms_exception(string msd = "dms exception")throw();
    //声明what方法
    virtual string what()throw();

private:
    string description; //描述
};

//服务器异常子类
class dms_server_exception :public dms_exception {
public:
    dms_server_exception(string msg = "server exception")throw();
};

//客户端异常子类
class dms_client_exception :public dms_exception {
public:
    dms_client_exception(string msg = "client exception")throw();
};

#endif // DMS_EXCEPTION_H
/*dms_exception.cpp*/
#ifndef DMS_EXCEPTION_H
#define DMS_EXCEPTION_H

#include 
using namespace std;

//异常的基类
class dms_exception {
public:
    dms_exception(string msd = "dms exception")throw();
    //声明what方法
    virtual string what()throw();

private:
    string description; //描述
};

//服务器异常子类
class dms_server_exception :public dms_exception {
public:
    dms_server_exception(string msg = "server exception")throw();
};

//客户端异常子类
class dms_client_exception :public dms_exception {
public:
    dms_client_exception(string msg = "client exception")throw();
};

#endif // DMS_EXCEPTION_H
/*main.cpp
*/
#include 
#include 
#include 

#include "dms_exception.h"

using namespace std;

//dms系统发送数据接口 ------ 服务器异常 客户端异常 ...
void send_data()
{
    srand(time(0));
    int r = rand() % 4;

    if (r == 0) {
        cout << "发送成功" << endl;
    }
    else if (r == 1) {//服务器异常
        throw dms_server_exception("dms服务器异常");
    }
    else if (r == 2) {//客户端异常
        throw dms_client_exception("dms客户端异常");
    }
    else if (r == 3) {//其他异常
        throw dms_exception("dms其他异常");
    }

}

int main()
{
    //执行可能抛出异常的代码
    try {
        send_data();
    }
    catch (dms_server_exception& e) {
        cout << "服务器异常" << endl;
        cout << e.what() << endl;
    }
    catch (dms_client_exception& e) {
        cout << "客户端异常" << endl;
        cout << e.what() << endl;
    }
    catch (dms_exception& e) {
        cout << "其他异常" << endl;
        cout << e.what() << endl;
    }

    return 0;
}

项目代码地址:https://github.com/Yu-1120/C-Plus

你可能感兴趣的:(c++,开发语言)