C++异常处理

        C++ 异常处理涉及到三个关键字:try、catch、throw。 在 c++程序中,任何需要检测异常的语句,都必须在 try 语句块中执行,异常必须由紧跟着 try 语句后面的 catch 语句来捕获并处理,因此 try 与 catch 总是结合使用,下面是它们的语法
throw 异常类型;


try
{
    //try 语句块
}
catch(类型 n 参数 n)
{
    //异常处理语句
}
throw 是用来抛出异常的,它抛出的异常类型可以是普通类型也可以是聚合类型。
基本类型:int、char、float
聚合类型:指针、数组、字符串、结构体
例如:
int init()
{
    int fd=open("1.txt",O_RDWR);
    if(fd==-1)
    {
        throw "打开失败"; //抛出字符串类型异常
    }
    char buf[128];
    int rd=read(fd,buf,128);
    if(rd==-1)
    {
        throw 1.88; //抛出浮点型类型异常
    }
    return 1;
}
        可以看到当程序出错时,就可以使用 throw 抛出不同异常类型,用以进行不同错误处理。
try 是用来检测抛出的错误的,例如:
try
{
    //下面两个函数可能会抛出异常
    int a = init();
    copyDir();
}
        通常,把可能会抛出异常的函数对象都包含在 try 中做检测。
而 catch 就是用来对抛出的错误进行判断和处理的,它必须在 try 的后面。
try
{
    int a=init();
    cout<<a<<endl;
}
catch(const char* na)
{
    cout<<na<<endl;
}
catch(float b)
{
    cout<<b<<endl;
}
catch(...) 
{
    cout<<"其他情况"<<endl;
}
        catch 会判断 try 检测到的异常的类型,根据类型开发者可以对其进行不同的处理(备注:C++
中…在 catch 中的作用相当于 default)

throw 的异常规范写法

        throw 关键字除了可以用在函数体中抛出异常,还可以用在函数头和函数体之间,指明当前函数能够抛出的异常类型,这称为异常规范(Exception specification)
第一种:例如:
double func ( char param ) throw ( int );
        声明了一个名为 func 的函数,它的返回值类型为 double,有一个 char 类型的参数,并且只能抛出 int 类型的异常。如果抛出其他类型的异常,try 将无法捕获,只能终止程序。
第二种:例如:
double func ( char param ) throw ( int , char , exception );
        函数可抛出多种类型的异常,用逗号隔开
第三种:例如:
double func ( char param ) throw ();
        如果函数不会抛出任何异常,那么( )中什么也不写,如此,func() 函数就不能抛出任何类型的异常了,即使抛出了,try 也检测不到。
        但是异常规范是 C++98 新增的一项功能,但是后来的 C++11 已经将它抛弃了,不再建
议使用,嘻嘻。

exception 异常类

        C++ 语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的异常。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。 之所以使用引用,是为了提高效率。如果不使用引用,就要经历一次对象拷贝(要调用拷贝构造函数)的过程。

        上面就是 std 中包含的一些异常类型,它们都是继承 exception 而来的,例如当使用了无效的参数时,就会抛出一个 std::invalid_argument 的错误,而程序开发者其实要定义新的异常类型时,可以继承 exception 类来做处理。

        上图是系统中 bad_alloc 异常类型的由来,可以看到他也是继承 exception 而来的,由此示例,当我们想要其他类型的异常处理的时,我们也可以根据上图的方法去继承一个新异常类型,例
如:
#include <iostream>
using namespace std;

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

int main() 
{
    try
    {
        throw MyException();
    }
    catch (MyException & e)
    {
        std::cout << e.what() << std::endl;
    }
    catch (std::exception & e)
    {
        //其他的错误
    }
    return 0;
}
        MyException 就是我们新创建的一个异常类型,当遇到一些相应的错误时,我们就可以返回这个异常类型,然后在这个异常类型的成员函数 what 中写入我们的错误处理提示。

异常层次

        同一个 try 语句块可以对应多个 catch 语句块,catch 语句块可以定义具体处理的异常类型,不同的类型的异常由不同的 catch 语句块处理;
        try 语句块可以抛出任何类型的异常,catch(...)用于处理所有类型的异常,任何异常都只能被捕获一次;
        throw 抛出的异常必须被 catch 处理,如果当前函数能够处理异常,继续执行;如果当前函 数不能处理异常,函数停止执行并返回;
        未被处理的异常会顺着函数调用栈向上传递,直到被处理为止,否则程序将停止执行。

noexcept 关键字

在上面说道在 C++11 之前,表示函数是否会抛出异常是通过在函数后面加入 throw 来说明的,具体查看 上面的异常规范,但是在 C++11 之后,就一般使用 noexcept 关键字来修饰函数是否会抛出异常了。
int close_t ( int s ) noexcept ;
        例如上面表名 close_t 函数绝对不会抛出异常,这是第一种形式,就是直接在函数后面加入
noexcept 关键字来表名函数绝对不会抛出异常,接下来看第二种。
int close_t ( int x , int y ) noexcept ( 1 > 0 )
{
        return 0 ;
}
        在 noexcept 后面可以加上一个常量表达式,表达式的值只能是 true 或 false,当为 true 时其作用就和直接写 noexcept 的效果是一样的,表明不会抛出异常,当为 false 的时候表明可能会抛出
异常。
最常用的就是就是用 noexcept 当运算符配合第二种方式进行,例如:
int fun()
{
    return 1;
}
int close_t(int x,int y) noexcept(noexcept(fun()))
{
    return 0;
}
        上面 fun()函数如果不抛出异常那么 noexcept(fun())就会返回 true,就相当于表明 close_t 也 不会抛出异常,使得两个函数的异常抛出情况相同。
或:
int close_t(int x,int y) noexcept(noexcept(x>y))
{
    return 0;
}
上面则是常用的根据函数参数情况来指定函数是否会抛出异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九月丫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值