c++异常

异常是程序在执行期间产生的问题,不是在编译期的问题,例如之前遇见的字符串下标越界问题。异常提供了一种转移程序控制权的方式,此时异常未经过正确的处理就会造成程序运行的崩溃。

处理异常的方式主要有两种:

● 捕获异常(try-catch)

● 抛出异常(throw)

C++的异常处理机制并不完善,是否使用取决于开发团队。

1.1 抛出异常

当程序咋运行期间出现问题时,C++运行系统会创建一个异常对象,此对象携带了一些本次出现异常的信息,并且抛给程序执行的函数。

#include <iostream>

using namespace std;

double divide(int a,int b)
{
    if(b==0)
    {
        throw "除数为零!";
        return -1;
    }
    return a/b;
}

int main()
{
    cout << "开始" << endl;

    string s;
    //    cout << s.at(-1); C++底层抛出给主函数的异常
    divide(1,0);

    cout << "终止" << endl;
    return 0;
}

1.2 捕获异常

如果某段代码可能有异常对象的抛出,可以使用try-catch代码块来捕获异常。

● try代码块

尝试执行某段可能出错的代码块,try块的代码尽量少。一个try块只能处理第一次出现的异常对象。

● catch代码块

如果try块出现了异常,catch块用固定的类型的异常处理代码来匹配try块中出现的异常类型,存在两种情况:

1. 匹配成功:从try块抛出异常处直接跳转到catch块。

2. 匹配失败:try-catch失效

C++中预定义了一些异常类型,使用时需要引入头文件<stdexcept>,如下所示:

 

1.2.1 最简单的单重捕获 


#include <iostream>
// 头文件
#include <stdexcept>

using namespace std;

double divide(int a,int b)
{
    if(b==0)
    {
        throw "除数为零!";
        return -1;
    }
    return a/b;
}

int main()
{
    cout << "开始" << endl;

    try
        {
            string s;
            cout << s.at(-1) << endl;
        }catch(out_of_range &e)
        {
            // 输出异常类型
            cout << e.what() << endl;
            // 补救措施
            cout << 'A' << endl;
        }

    try
        {
            cout << divide(1,0) << endl;
        }catch(const char* e)
        {
            // 输出异常类型
            cout << e << endl;
            // 补救措施
            cout << "无穷" << endl;
        }

    cout << "终止" << endl;
    return 0;
}

 

1.2.2 不精准的捕获

有时候无法精准地判断异常出现的固定的类型,此时可以使用异常的基类进行捕获,这种的优势是只要捕获的类型是抛出的类型的基类即可成功,劣势是无法精准匹配,补救措施的效率可能会降低。

#include <iostream>
// 头文件
#include <stdexcept>

using namespace std;


int main()
{
    cout << "开始" << endl;

    try
        {
            string s;
            cout << s.at(-1) << endl;
        }catch(out_of_range &e) // out_of_range → logic_error → exception(...)
        {
            cout << e.what() << endl;
            cout << 'A' << endl;
        }

    cout << "终止" << endl;
    return 0;
}

1.2.3 多重捕获

一个try块同时配合多个catch块进行多重异常类型的捕获,多重捕获支持派生类异常与基类异常同时使用,但是基类异常要放在派生类异常的后面。

#include <iostream>
// 头文件
#include <stdexcept>

using namespace std;


int main()
{
    cout << "开始" << endl;

    try
        {
            string s;
            cout << s.at(-1) << endl;
        }catch(length_error &e)
        {
            cout << e.what() << endl;
            cout << 'A' << endl;
        }catch(out_of_range &e)
        {
            cout << e.what() << endl;
            cout << 'B' << endl;
        }catch(logic_error &e)
        {
            cout << e.what() << endl;
            cout << 'C' << endl;
        }catch(exception &e)
        {
            cout << e.what() << endl;
            cout << 'D' << endl;
        }

    cout << "终止" << endl;
    return 0;
}

1.3 自定义异常

C++标准异常类型较少,如果要使用异常处理机制,还需要自己定义不同的异常类型。

#include <iostream>
#include <stdexcept>

using namespace std;


class DividedException:public exception
{
public:
const char* what() const throw()
//异常规格说明,表示what()可以抛出异常的类型,()为空。表示what本身不抛出异常。
{
    return "除数为0!";
}
};


double divide(int a,int b)
{
    if(b==0)
    {
        throw DividedException();
        return -1;
    }
    return a/b;
}


int main()
{
    cout << "开始" << endl;

    try
        {
            cout << divide(1,0) << endl;
        }catch(DividedException &e)
        {
            cout << e.what() << endl;
            cout << -1 << endl;
        }

    cout << "终止" << endl;
    return 0;
}

1.4 栈自旋

#include <iostream>
using namespace std;
class A
{
public:
    A()
    {
    	cout<<"A constructor"<<endl;
    }
    ~A()
    {
    	cout<<"~A destructor"<<endl;
    }
};
int divide(int x, int y)
{
    A a;
    if(y == 0)
    	throw('a');
    return x/y;
}
int myDivide(int x, int y)
{
    A b;
    divide(x,y) ;
}
int main()
{
    try{
    	myDivide(4,0);
    }catch(int x){
        cout<<"x"<<endl;
        cout<<x<<endl;
    }catch(double y){
        cout<<"y"<<endl;
        cout<<y<<endl;
    }catch(...){
    	cout<<"no x, no y"<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值