C++ 异常机制

1. 传统的错误处理

1.1 程序开发中常见的错误

在这里插入图片描述

1.2 传统错误处理方式

在这里插入图片描述

2. C++的异常机制

在这里插入图片描述

2.1 正常流程

在这里插入图片描述

2.2 异常流程

在这里插入图片描述

2.2.1 throw抛出基本类型:

#include <iostream>
#include <cstdio>
using namespace std;

class A{
public:
    A(void){
        cout << "A类构造" << endl;
    }
    ~A(void){
        cout << "A类析构" << endl;
    }
};

int func3(void){
    A a;
    FILE *fp = fopen("x.txt", "r");
    if(fp == NULL){
        throw -1; // 抛出异常, 不会执行下面的代码,只会执行}, 这样就可以调用A的析构
    }
    //...
    fclose(fp);
    return 0;
}

int func2(void){
    A a;
    // 若func3中 throw抛出异常,那么这里func3()下面的代码也不会执行,只会执行},这样就可以调用A类析构
    func3();
    //...
    return 0;
}

int func1(void){
    A a;
    // 若func3中 throw抛出异常,那么这里func2()下面的代码也不会执行,只会执行},这样就可以调用A类析构
    func2();
    //...
    return 0;
}

int main(void){
    try{            // 异常检测
        // 检测到异常以后,会逐层返回,只执行}, 不执行代码
        func1();
        //并且检测到异常以后不会再执行下面的代码
        cout << "test" << endl;
    }
    catch(int ex){  // 异常捕获
        cout << "文件打开失败" << endl;
        return -1;
    }
}
$ ./a.out 
A类构造
A类构造
A类构造
A类析构
A类析构
A类析构
文件打开失败

2.2.2 throw抛出类类型:

#include <iostream>
#include <cstdio>
using namespace std;

class FileError{
public:
    FileError(const string& file, int line):m_file(file), m_line(line){
        cout <<"出错位置"<< m_file <<", 出错行号" << m_line << endl;
    }
private:
    string m_file;
    int m_line;
};

class A{
public:
    A(void){
        cout << "A类构造" << endl;
    }
    ~A(void){
        cout << "A类析构" << endl;
    }
};


int func3(void){
    A a;
    FILE *fp = fopen("x.txt", "r");
    if(fp == NULL){
        throw FileError(__FILE__, __LINE__); //匿名的方式创建了一个FileError对象, 然后被throw抛出, 下面的throw -1; 不会执行
        throw -1; // 抛出异常, 不会执行下面的代码,除了}, 这样就可以调用A的析构
        
    }
    //...
    fclose(fp);
    return 0;
}

int func2(void){
    A a;
    // 若func3中 throw抛出异常,那么这里func3()下面的代码也不会执行,只会执行},这样就可以调用A类析构
    func3();
    //...
    return 0;
}

int func1(void){
    A a;
    // 若func3中 throw抛出异常,那么这里func2()下面的代码也不会执行,只会执行},这样就可以调用A类析构
    func2();
    //...
    return 0;
}


int main(void){
    try{            // 异常检测
        // 检测到异常以后,会逐层返回,只执行}, 不执行代码
        func1();
        //并且检测到异常以后不会再执行下面的代码
        cout << "test" << endl;
    }
    catch(int ex){  // 异常捕获
        cout << "文件打开失败" << endl;
        return -1;
    }
    // 引用做参数避免拷贝构造
    catch(FileError& ex){
        cout << "File open Error" << endl;
    }
}
$ ./a.out 
A类构造
A类构造
A类构造
出错位置a.cpp, 出错行号30
A类析构
A类析构
A类析构
File open Error
  • 对于函数调用,只有知道函数中,throw会抛出的异常类型。才能去写catch语句, 所以就有了 函数的异常说明

3. 函数的异常说明

在这里插入图片描述

#include <iostream>
#include <cstdio>
using namespace std;

class FileError{};
class MemoryError{};

void func(void) throw (MemoryError){
    // 这里抛出的对象的类型一定要是异常类型表里的一种类型
    throw MemoryError();
    //  // 如果不是,异常不会被catch捕获,而是会被系统系统捕获, 比如下面, 然后终止这个进程
    // throw FileError();
}
int main(void){
    try{
        func();
    }
    catch(MemoryError& ex){
        cout << "MemoryError" << endl;
    }
    catch(FileError& ex){
        cout << "FileError" << endl;
    }
}
 $ ./a.out 
MemoryError

4. 标准异常类的说明

在这里插入图片描述

  • 用一个catch处理多个异常。
#include <iostream>
#include <cstdio>
using namespace std;

class FileError:public exception{
public:
    //  const char* what() const _GLIBCXX_USE_NOEXCEPT{ // 也行
    const char* what() const throw(){
        cout << "针对文件错误的处理" << endl;
        return "FileError";
    }
};

class MemoryError:public exception{
public:
    //  const char* what() const _GLIBCXX_USE_NOEXCEPT{ // 也行
    const char* what() const throw(){
        cout << "针对内存错误的处理" << endl;
        return "MemoryError";
    }
};

void func(void) throw (MemoryError, FileError){
    // 这里抛出的对象的类型一定要是异常类型表里的一种类型
    throw MemoryError();
}
int main(void){
    try{
        func();
    }
    // 基类类型引用接收子类对象(向上造型)
    catch(exception& ex){
        // 多态语法, 调用实际被引用对象中的虚函数what
        ex.what();
    }
}
$ ./a.out 
针对内存错误的处理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值