017-异常

2021-10-07  本文已影响0人  一亩三分甜

《C++文章汇总》
上一篇介绍了《016-Lamda表达式、C++14和C++17新特性》,本文介绍异常。

1.错误

◼ 编程过程中的常见错误类型 语法错误

逻辑错误
异常
......

2.异常

◼ 异常是一种在程序运行过程中可能会发生的错误(比如内存不够)

int main(){
    cout << 1 << endl;
    for (int i = 0; i<99999; i++) {
        //这句代码可能会产生异常(抛出异常)
        try {
            int *p = new int[9999999];
            cout << 2 << endl;
            /**
             ...
             */
        } catch (...) {
            cout << "产生异常了:内存不够用" << endl;
            break;
        }
    }
    cout << 3 << endl;
}

◼ 异常没有被处理,会导致程序终止,后面的代码不会执行

被除数为0,系统不会抛异常,直接闪退,程序员手动抛异常


图片.png
int divide(int v1,int v2){
    if (v2 == 0) {
        throw 999;
    }
    return v1/v2;;
}
int main(){
   
    try {
        int a = 10;
        int b = 0;
        int c = divide(a, b);
        cout << c << endl;
    } catch (...) {
        cout << "产生异常了" << endl;
    }
    
    getchar();
    return 0;
}
//输出
产生异常了

抛出字符串异常

int divide(int v1,int v2){
    if (v2 == 0) {
        //抛出异常
        throw "不能除以0";
    }
    return v1/v2;;
}
int main(){
    cout << 1 << endl;
    try {
        int a = 10;
        int b = 0;
        int c = divide(a, b);
        cout << c << endl;
    } catch (const char *exception) {
        cout << "产生异常了:" << exception << endl;
    }
    cout << 2 << endl;
    getchar();
    return 0;
}
//输出
1
产生异常了:999
2
图片.png
try {
    int a = 10;
    int b = 0;
    int c = divide(a, b);
    cout << c << endl;
} catch(int exception){
    cout << "产生异常了:int exception" << exception << endl;
}catch (const char *exception) {
    cout << "产生异常了:const char *exception" << exception << endl;
}

◼ throw异常后,会在当前函数中查找匹配的catch,找不到就 终止当前函数代码,去上一层函数中查找。如果最终都找不 到匹配的catch,整个程序就会终止
异常没有被处理,程序中止

void func1(){
    cout << "func1-begin" << endl;
    throw 666;//throw 666
    cout << "func1-end" << endl;
};
void func2(){
    cout << "func2-begin" << endl;;
    func1();//throw 666
    cout << "func2-end" << endl;
};
int main(){
    cout << "main-begin" << endl;
    func2();//throw 666
    cout << "main-end" << endl;
    
    getchar();
    return 0;
}
//输出
main-begin
func2-begin
func1-begin
libc++abi.dylib: terminating with uncaught exception of type int
图片.png

异常被捕获,程序正常执行

void func1(){
    cout << "func1-begin" << endl;
    try{
        throw 666;
    }catch(int exception){
        cout << "产生异常了:(int)" << exception << endl;
    }
    cout << "func1-end" << endl;
};
void func2(){
    cout << "func2-begin" << endl;;
    func1();
    cout << "func2-end" << endl;
};
int main(){
    cout << "main-begin" << endl;
    func2();
    cout << "main-end" << endl;
    
    getchar();
    return 0;
}
//输出
main-begin
func2-begin
func1-begin
产生异常了:(int)666
func1-end
func2-end
main-end

异常时严谨匹配,double类型的exception获取不到int类型的异常


图片.png

抛异常在函数捕获终止位置,抛异常后面的代码不会执行

void func1(){
    cout << "func1-begin" << endl;
    throw 666;
    cout << "func1-end" << endl;
};
void func2(){
    cout << "func2-begin" << endl;;
    func1();
    cout << "func2-end" << endl;
};
int main(){
    cout << "main-begin" << endl;
    try{
        func2();
    }catch(int exception){
        cout << "产生异常了:(int)" << exception << endl;
    }
    cout << "main-end" << endl;
    
    getchar();
    return 0;
}
//输出
main-begin
func2-begin
func1-begin
产生异常了:(int)666
main-end

3.异常的抛出声明

◼ 为了增强可读性和方便团队协作,如果函数内部可能会抛出异常,建议函数声明一下异常类型


图片.png

4.自定义异常类型

//所有异常的基类
class Exception{
public:
    virtual const char *what() = 0;
    
};
class DivideException:public Exception{
public:
    const char *what(){
        return "不能除以0";
    };
    int code(){
        return 303;;
    }
};
class AddException:public Exception{
public:
    const char *what(){
        return "加法有问题";
    };
    int code(){
        return 202;;
    }
};
int divide(int v1,int v2){
    if (v2 == 0) {
        //抛出异常
        throw DivideException() ;
    }
    return v1/v2;;
}
void test4(){
    cout << 1 << endl;
    try {
        int a = 10;
        int b = 0;
        cout << divide(a, b) << endl;
    } catch (DivideException exception) {
        cout << "产生异常了(DivideException) " << exception.what() << endl;
    }catch(AddException exception){
        cout << "产生异常了(AddException) " << exception.what() << endl;
    }
    cout << 2 << endl;
}
int main(){
    test4();
    getchar();
    return 0;
}
//输出
1
产生异常了(DivideException) 不能除以0
2

基类异常接收子类的异常,统一接收,不管什么异常都统一接收

class DivideException:public Exception{
public:
    const char *what() const{
        return "不能除以0";
    };
    int code() const{
        return 303;;
    }
};
class AddException:public Exception{
public:
    const char *what() const{
        return "加法有问题";
    };
    int code() const{
        return 202;;
    }
};
int divide(int v1,int v2){
    if (v2 == 0) {
        //抛出异常
        throw DivideException() ;
    }
    return v1/v2;;
}
void test4(){
    cout << 1 << endl;
    try {
        int a = 10;
        int b = 0;
        cout << divide(a, b) << endl;
    } catch (const Exception &exception) {
        cout << "产生异常了(Exception) " << exception.what() << endl;
    }
    cout << 2 << endl;
}
int main(){
    test4();
    getchar();
    return 0;
}
//输出
1
产生异常了(Exception) 不能除以0
2

5.标准异常(std)

图片.png
图片.png
int main(){
//    test4();
    cout << 1 << endl;
    for (int i = 0; i<999999; i++) {
        try {
            int *p = new int[9999999];
        } catch (bad_alloc exception) {
            cout << "产生异常了:内存不够用" << exception.what() <<endl;
            break;
        }
    }
    cout << 2 << endl;
}
//输出
1
产生了异常:内存不够用 - bad allocation
2

也可直接使用父类exception

int main(){
//    test4();
    cout << 1 << endl;
    for (int i = 0; i<999999; i++) {
        try {
            int *p = new int[9999999];
        } catch (const exception &exception) {
            cout << "产生异常了:内存不够用" << exception.what() <<endl;
            break;
        }
    }
    cout << 2 << endl;
}
//输出
1
产生了异常:内存不够用 - bad allocation
2
上一篇 下一篇

猜你喜欢

热点阅读