Fork me on GitHub

C++——异常处理

前言

大型和十分复杂的程序往往会产生一些很难查找的甚至是无法避免的运行时错误。当发生运行时错误时,不能简单地结束程序运行,而是退回到任务的起点,指出错误,并由用户决定下一步工作。面向对象的异常处理(exception handling)机制是C++语言用以解决这个问题的有力工具。函数执行时,放在try(测试)程序块中的任何类型的数据对象发生异常,都可被throw块抛出,随即沿调用链退回,直到被catch块捕获,并在此执行异常处理,报告出现的异常等情况。从抛出到捕获,应将各嵌套调用函数残存在栈中的自动对象、自动变量和现场保护内容等进行清除。如果已退到入口函数还未捕获则由abort()来终结入口函数。

这里所讲的异常(exception)是程序可能检测到的,运行时不正常的情况,如存储空间耗尽、数组越界、被0除等等,可以预见可能发生在什么地方,但是无法确知怎样发生和何时发生。特别在一个大型的程序(软件)中,程序各部分是由不同的小组编写的,它们由公共接口连起来,错误可能就发生在相互的配合上,也可能发生在事先根本想不到的个别的条件组合上。

C++提供了一些内置的语言特性来产生(raise)或抛出(throw)异常,用以通知“异常已经发生”,然后由预先安排的程序段来捕获(catch)异常,并对它进行处理。这种机制可以在C++程序的两个无关(往往是独立开发)的部分进行“异常”通信。由程序某一部分引发了另一部分的异常,这一异常可回到引起异常的部分去处理(沿着程序函数的调用链)。这也是分清处理责任的好办法。

异常规范

C++函数有2个返回值,左侧是正常返回,右侧是异常返回

float Div(int a,int b)默认是抛出所有异常

float Div(int a,int b)throw(int,short,Test)规定只能抛出int、short、Test类型的异常。如果是float类型异常,则无法抛出

异常处理的机制

首先,在C++中异常往往用类(class)来实现,以栈为例,异常类声明如下:
class popOnEmpty{...}; //栈空异常
class pushOnFull{...}; //栈满异常

#include<iostream>
#include<string>
using namespace std;
template<typename Type>
class PushOnStackFull
{
public:
    PushOnStackFull(const char *s, int val) :str(s), value(val)
    {}
    ~PushOnStackFull()
    {}
public:
    void _What() const
    {
        cout << str << endl;
        cout << value << " not push stack" << endl;
    }
private:
    Type value;
    string str;
};
template<typename Type>
class Stack
{
public:
    Stack(int sz = STACK_SIZE)
    {
        capacity = sz > STACK_SIZE ? sz : STACK_SIZE;
        data = new Type[capacity];
        top = 0;
    }
    ~Stack()
    {
        delete []data;
        data = NULL;
        capacity = 0;
        top = 0;
    }
public:
    bool IsFull()const
    {
        return top >= capacity;
    }
    bool Push(const Type &x)
    {
        if (IsFull())
        {
            throw PushOnStackFull<Type>("栈已满不能入栈",x);
        }
        data[top++] = x;
        return true;
    }
    void Show_Stack()const
    {
        for (int i = top - 1; i >= 0; --i)
        {
            cout << data[i] << endl;
        }
    }
private:
    enum { STACK_SIZE =8};
    Type * data;
    size_t capacity;
    size_t top;
};

int main()
{
    Stack<int> st;
    try 
    {
        for (int i = 1; i < 10; ++i)
        {
            st.Push(i);
        }
    }
    catch (PushOnStackFull<int> &e)
    {
        e._What();
    }
    st.Show_Stack();
    return 0;
}
View Code

 

posted @ 2018-09-01 21:36  克拉默与矩阵  阅读(441)  评论(0编辑  收藏  举报