异常处理

异常时程序在执行期间产生的问题。C++异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。

异常提供了一种转移程序控制权的方式。C++异常处理涉及到三个关键字:try、catch、throw

throw:当问题出现时,程序回抛出一个异常。这是通过使用throw关键字来完成。

catch:当你想处理问题的地方,通过异常处理程序捕获异常。catch关键字用于异常捕捉。

try:try块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个catch块。

如果有一个块抛出一个异常,捕获异常的方法会使用try和catch关键字。try中放置可能抛出异常的代码。try块中的代码被称为保护代码。使用try/catch语句的语法如下:

try
{
    //保护代码
}
catch(ExceptionName e1)
{
    //catch块
} 
catch(ExceptionName e2)
{
    //catch块
} 
catch(ExceptionName eN)
{
    //catch块
}

如果try块在不同情境下会抛出不同的异常,这个时候就可以尝试罗列出多个catch语句,用于捕获不同的异常。

抛出异常

可以使用throw语句在代码块中的任何地方抛出异常,throw语句的操作数可以时任意的表达式,表达式的结果的类型决定了抛出的异常的类型。

实例:

/***
try.cpp
***/
#include<iostream>
using namespace std;

double division(int a,int b)
{
    if(b == 0)
    {
        throw "Division by zero condition";
    }
    return a/b;
}

int main()
{
    int x = 50;
    int y = 0;
    double z = 0;
    try
    {
        z = division(x,y);
        cout << z << endl;
    }
    catch(const char *msg)
    {
        cerr << msg << endl;
    }
    return 0;
}

由于我们抛出一个类型为const char* 的异常,因此,当捕获该异常时,我们必须在catch块中使用const char*。

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190813$ g++ try.cpp -o try

exbot@ubuntu:~/wangqinghe/C++/20190813$ ./try

Division by zero condition

C++标准异常

C++提供了一系列标准的异常,定义在<expection>中,我们可以在程序中使用这些标准的异常,他们是以父子类层次结构组织起来的。

下图是对上层结构中出现的每个异常的说明:

 定义新的异常

可以通过继承和重载exception来定义新的异常。

/***
exception.cpp
***/
#include<iostream>
#include<exception>
using namespace std;

struct MyException:public exception
{
    const char* what() const throw()
    {
        return "C++ Exception";
    }
};

int main()
{
    try
    {
        throw MyException();
    }
    catch(MyException& e)
    {
        cout << "MyException caught" << endl;
        cout << e.what() << endl;
    }
    catch(exception& e)
    {
        //
    }
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190813$ ./exception

MyException caught

C++ Exception

在这里,what()是异常类提供的一个公共方法,它已被所有子异常类重载。这将返回异常产生的原因。

const throw()不是函数,这个东西叫异常规格说明,表示what函数可以抛出异常的类型,类型说明放在()里,这里面没有类型,就是声明这个函数不抛出异常,通常这个函数不写后面的就表示函数可以抛出任何类型的异常。

异常规格说明

  1. 异常规格说明的目的就是为了让函数使用者知道该函数可能从哪里抛出的异常有哪些。可以在函数的声明中列出这个函数可能抛出的所有异常类型。例如:

void fun() throw(A,B,C,D)

  1. 如无异常接口说明,则此函数可以抛掷任何类型的异常。
  2. 不抛掷任何类型异常的函数声明如下:
/***
exception.cpp
***/
#include<iostream>
#include<exception>
using namespace std;

class MyException
{
public:
    MyException(const char *message):message_(message)
    {
        cout << "MyException ..." << endl;
    }
    MyException(const MyException &other):message_(other.message_)
    {
        cout << "copy MyException ... " << endl;
    }
    virtual ~MyException()
    {
        cout << "~MyException ..." << endl;
    }
    const char* what() const 
    {
        return message_.c_str();
    }
private:
    string message_;
};

class MyExceptionD : public MyException
{
public:
    MyExceptionD(const char*message):MyException(message)
    {
        cout << "MyExceptionD ..." << endl;
    }
    MyExceptionD(const MyExceptionD &other):MyException(other)
    {
        cout << "Copy MyExceptionD ..." << endl;
    }
    ~MyExceptionD()
    {
        cout << "~MyException..." << endl;
    }
};

void fun(int n) throw(int ,MyException,MyExceptionD)
{
    if(1 == n)
    {
        throw 1;
    }
    else if(2 == n)
    {
        throw MyException("test Exception");
    }
    else if(3 == n)
    {
        throw MyException("test ExceptionD");
    }
}

void fun2() throw()
{

}

int main()
{
    try
    {
        fun(2);
    }
    catch(int n)
    {
        cout << "catch int ..." << endl;
        cout << "n = " << n << endl;
    }
    catch(MyExceptionD &e)
    {
        cout << "catch MyExceptionD ..." << endl;
        cout << e.what() << endl;
    }
    catch(MyException &e)
    {
        cout << "catch MyException ..." << endl;
        cout << e.what() << endl;
    }
    return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190814$ g++ exception.cpp -o exception

exbot@ubuntu:~/wangqinghe/C++/20190814$ ./exception

MyException ...

catch MyException ...

test Exception

~MyException ...

原文地址:https://www.cnblogs.com/wanghao-boke/p/11350272.html