首页 > 编程语言 >C++温故补缺(十一):异常

C++温故补缺(十一):异常

时间:2023-03-20 23:22:28浏览次数:53  
标签:int 温故 捕获 C++ try 补缺 catch 异常 throw

异常处理

参考:cnblogs

异常和错误(bug)

异常:是程序开发过程中必须考虑的一些特殊情况,是程序运行时可以预料的执行分支。异常是不可以避免的,如0除问题,数组越界问题,文件不存在问题等。但是可以处理,通过抛出,捕获异常,可以使程序继续运行

错误:是程序的缺陷,是程序运行时无法预料的运行方式,一旦发生错误,程序将会被终止

如:

遇到错误时:

#include<iostream>
using namespace std;

int main(){
    const int a=10;
    a++;
}

程序会终止运行

而遇到异常时,可以抛出,捕获,程序不会因为异常而终止运行,而是在抛出异常后继续运行后续代码

#include<iostream>
using namespace std;

void divide(int x,int y){
    if(y==0){
        throw -1;
    }
    cout<<x/y;
}

int main(){
    try{
        divide(20,0);
    }catch(int){
        cout<<"零除异常"<<endl;
    }
    cout<<"over"<<endl;
}

如上,在遇到异常时,throw抛出一个表达式,可以是任意类型的,但是catch时要和throw抛出的表达式类型相同,如这里抛出-1,catch就要捕获int,如果抛出了"exception"这样的字符串,catch就要捕获const char*类型。

捕获完就可以处理异常,处理异常的过程是直接跳转到catch语句后,throw后面的语句便不再执行。

如:

#include<iostream>
using namespace std;


int main(){
    try{
        cout<<"hello";
        throw -1;
        cout<<"Tom";
    }catch(int a){
        cout<<"异常:"<<a<<endl;
    }
}

throw 出异常后,其后面的输出不再执行

且如上,catch捕获的不止throw表达式类型,同时可以赋给一个变量,然后在catch块中使用

异常的基本原则

  • 通常,异常的抛出和捕获并不是在同一个函数中进行的,假设在函数B()中遇到了异常,并不会直接在B中捕获处理异常,而是抛出给它的调用者假设为A(),
B(){
    ...
    throw -1;
}
A(){
    try{
    B();
}catch(int){
    ...
}
}

如果A中没有捕获异常,程序将会自动继续向上抛出给A的调用者,一直到main()函数,如果都没有捕获异常,程序将终止执行

  • 一个try语句后可以跟多个catch语句,捕获多种类型的异常,但至少有一个catch块

  • 使用catch(...)可以捕获任意类型的异常

  • 异常只能被一个catch捕获,一旦被捕获,其他的catch就没有捕获机会了

try..catch嵌套(在catch中重新抛出异常)

try...catch可以嵌套使用,也就是内层的catch捕获到异常后什么都不做,直接抛出,由上一层的catch来处理异常,如:

#include<iostream>
using namespace std;

int main(){
    try{
        try{
            cout<<"内层抛出异常"<<endl;
            throw -1;
        }catch(int){
            throw 'a';
        }
    }catch(char){
        cout<<"外层处理异常"<<endl;
    }
}

为什么要在catch语句中重新抛出异常?

第三方库的异常解释可读性很差,甚至需要查手册才能知道什么异常,比如直接抛出一些数值,像windows系统中常见的error:-1,error:#0x0081之类的,根本不可能通过这些信息知晓异常的详情

所以在引入第三方库后,如果遇到这些异常,就捕获了重新抛出,然后加入一些自定义的解释,来增加可读性

模拟:

#include<iostream>
using namespace std;

void lib(){
    throw -1;
}

void myfunc(){
    try{
        lib();
    }catch(int a){
        if(a==-1){
            throw "参数错误";
        }
    }
}
int main(){
    try{
        myfunc();
    }catch(const char* str){
        cout<<"发生异常:"<<str<<endl;
    }
}

自定义异常类

异常类是可以自定义的,用于整个大工程,将通用的异常集合起来管理。且异常类通常也会有派生类,一般也类似一个Exception父类,派生多种不同的异常类。在赋值兼容性原则中,一般将匹配子类异常的catch放在上部,匹配父类异常的catch放在下部。

例子:

#include<iostream>
using namespace std;

class Exception{
    private:
        int Eid;
        string Edes;
    public:
        Exception(int id,string des){
            Eid=id;
            Edes=des;
        };

        int getEid(){return Eid;};
        string getEdes(){return Edes;};
};
void lib(){
    throw -1;
}

void myfunc(){
    try{
        lib();
    }catch(int a){
        if(a==-1){
            throw Exception(-1,"参数错误");
        }
    }
}
int main(){
    try{
        myfunc();
    }catch(Exception e){
        cout<<"发生异常:"<<e.getEid()<<e.getEdes()<<endl;
    }
}

C++标准库中的异常类

标签:int,温故,捕获,C++,try,补缺,catch,异常,throw
From: https://www.cnblogs.com/Tenerome/p/cppreview11.html

相关文章

  • C++温故补缺(十):C++文件读写和流
    C++文件和流C++文件的读写流用的是fstream库,它定义了三个新的数据类型:数据类型描述ofstream该数据类型表示输出文件流,用于创建文件并向文件写入信息。ifstr......
  • 面试高频问题之C++11新特性
    背景C++11是C++语言的一个重大更新,引入了许多新特性,包括自动类型推导、lambda表达式、右值引用、智能指针等等。这些新特性使得C++更加现代化、高效、易用。也是面试容很容......
  • 面试高频问题之C++11新特性
    背景C++11是C++语言的一个重大更新,引入了许多新特性,包括自动类型推导、lambda表达式、右值引用、智能指针等等。这些新特性使得C++更加现代化、高效、易用。也是面试容很......
  • [第十届蓝桥杯省赛C++B组]等差数列
    来源:第十届蓝桥杯省赛C++B组算法标签:数论最大公约数题目描述数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中N个整数。现在给......
  • 以下是一个使用C++实现HTTP文件下载的简单示例,其中使用了C++ 11的标准库和Boost库:
    #include<iostream>#include<fstream>#include<boost/asio.hpp>usingboost::asio::ip::tcp;intmain(){try{boost::asio::io_serviceio_service;......
  • c++环境
    目录环境准备下装安装vscode及插件安装mingw编译器工作环境准备vscode工作目录调试环境CSDN参考文档环境准备下装安装vscode及插件vscode是微软账号登录的插件配置信息......
  • [C++引用] 保定丽丽带你学C++
    引用是C++内一个比较有用的方法,大家在丽丽的带领下好好学习。一.引用的基本使用C++引用的作用:给变量起别名语法:​​数据类型&名字=原名​​示例:#include<iostream>usi......
  • C++重载
    返回值不能作为重载的依据intfun()const;intfun();常成员函数可以用于重载无法重载的情况voidfun(inta);voidfun(constinta);普通值传递和const传递无法......
  • C++ 读写ini文件
    #include<Windows.h>#include<string>classIniFile{public:IniFile(conststd::wstring&path):m_path(path){}std::wstringGetValue(conststd::wstring&......
  • C++ map用法总结(整理)
    C++map用法总结(整理)1,map简介map是STL的一个关联容器,它提供一对一的hash。第一个可以称为关键字(key),每个关键字只能在map中出现一次;第二个可能称为该关键字的值(valu......