前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++异常处理

C++异常处理

作者头像
用户2929716
发布2018-08-23 13:20:47
6190
发布2018-08-23 13:20:47
举报
文章被收录于专栏:流媒体流媒体

要点

  • 异常根据抛出的类型捕获,可以直接捕获接收或通过引用接收。但二者同时只能存在一个。
  • 栈内存创建的对象指针抛出后会产生野指针问题
  • 动态创建对象的指针抛出后可以正常捕获使用,但是需要手动释放。
  • 函数声明可以加上异常声明。限制函数可以抛出的异常类型。
  • 异常有栈解锁机制,栈内存中创建的对象在异常抛出后会自动析构。
  • 异常可以捕获并继续向上抛出。

示例代码

代码语言:javascript
复制
#include "stdafx.h"
#include "iostream"
#include "string.h"
using namespace std;
#pragma warning(disable : 4996)  
class ExceptionA {
private:
    char *msg;
public:
    ExceptionA(const char *msg) {
        cout << "构造" <<msg<< endl;
        if (msg == NULL) {
            this->msg = NULL;
        }else{
            this->msg = new char[strlen(msg) + 1];
            strcpy(this->msg, msg);
        }
    }
    char * getMsg()const {
        return this->msg;
    }
    ExceptionA(const ExceptionA& e) {
        cout << "拷贝构造" << endl;
        if (this->msg == NULL) {
            delete[]this->msg;
        }
        this->msg = new char[strlen(e.getMsg()) + 1];
        strcpy(this->msg, e.getMsg());
    }
    ~ExceptionA() {
        cout << "析构" << msg << endl;
        if (this->msg != NULL) {
            delete[]this->msg;
        }
    }
};

void funcA(int x) {

    switch (x)
    {
    case 0:{
        //throw异常后,temp1会自动析构,而temp不会自动析构和释放
        ExceptionA *temp = new ExceptionA("temp");
        ExceptionA temp1("temp1");
        throw 1;
    }
        break;
    case 1:
        throw 'a';
        break;
    case 2:
        //可以直接接受或使用引用接收。推荐使用引用接收
        throw(ExceptionA("msg 2"));
        break;
    case 3:
        //抛出指针,但对象会被清理。catch到的指针是野指针
        throw(&ExceptionA("msg 3"));
        break;
    case 4: {
        //抛出动态分配的指针。catch到后使用完后需要delete
        ExceptionA* e = new ExceptionA("msg4");
        throw(e);
    }
        break;
    case 5:
        throw 3.14f;
    case 6:
        throw 3.14;
    }
    cout << "funcA success " << x << endl;
}

void funcB(int index) throw(float ,double){
    try {
        funcA(index);
    }
    catch (int e) {
        cout << "catch int " << e << endl;
    }
    catch (char e) {
        cout << "catch char " << e << endl;
    }
    catch (ExceptionA e) {
        cout << "catch  ExceptionA " << e.getMsg() << endl;
    }
    //使用对象接收和使用对象的引用接收不能同时存在。
    //catch (ExceptionA &e) {
    //  cout << "catch  ExceptionA & " << e.getMsg() << endl;
    //}
    catch (ExceptionA *e) {
        cout << "catch  ExceptionA * " << e->getMsg() << endl;
        delete e;
    }
    catch (float e) {
        //接续向上抛出异常
        cout << "catch float and throw  " << e << endl;
        throw e;
    }
    catch (double e) {
        //接续向上抛出异常,但函数的方法上有限制可以抛出异常的类型。这里会出错
        cout << "catch double and throw  " << e << endl;
        throw e;
    }
}
int main()
{
    try {
        funcB(6);
    }
    catch (float e) {
        cout << "main catch " << e << endl;
    }
    return 0;
}

异常处理场景演示

  • funcB(0)

0.png 这里创建了两个对象一个在堆中动态创建temp.一个在栈中temp1。执行结果看到temp1自动被析构,而temp未被析构。c++在异常抛出后有栈解锁机制,会自动析构在栈中创建的对象。

  • funcB(1)

1.png 这里就是按类型在funcA中正常的catch

  • funcB(2) 栈内存对象
    • 用对象直接接收

    2.png 这里看到当抛出对象时候,catch中接受时类似方法实参到形参的传递,进行拷贝构造。

    • 用对象的引用接收

    7.png catch中得到对象的引用。

  • funcB(3) 抛出栈内存对象的指针

3 catch得到对象的指针前。对象已被析构,这里得到的就是野指针。

  • funcB(4) 动态创建对象

4.png 可以正常catch到并使用。但使用完后需要手动释放。

  • funcB(5) 捕获到异常后继续向上抛出

5.png funcA中继续抛出,在main中正常捕获。

  • funcB(6) 方法异常类型声明

6.png 限制方法能够抛出异常的类型,如果不在范围内,运行会报错

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.08.24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 要点
  • 示例代码
  • 异常处理场景演示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档