问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C++关键字 | throw、try、catch异常处理关键字

创作时间:
作者:
@小白创作中心

C++关键字 | throw、try、catch异常处理关键字

引用
CSDN
1.
https://blog.csdn.net/HaohaoCppDebuger/article/details/121935973

前言
throw
关键字仅可用于C++

关于异常

异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。

在C语言中,如果程序的运行出现异常、错误,我们想提供方案处理这些异常时,我们面临许多问题,如:

  1. c语言没有提供统一(标准)的方式来处理错误;
  2. 无法保证错误会被正确的处理;
  3. 错误的传播无法控制,特别是在函数的嵌套调用时;

而C++提供了处理异常的关键字:

throw

try

catch
**。

抛出异常

你可以使用
throw
抛出一个异常:

throw err;

如:

throw"Division by 0!";
throw 0x12345fff;

捕获异常

使用
try

catch
捕获异常:

try{
    ...//保护代码
}catch(Ex e1){
    ...//异常处理
}catch(Ex e2){
    ...//异常处理
}catch(Ex eN){
    ...//异常处理
}

try
块后面通常跟着1个或多个
catch
块,用于捕获保护代码里可能抛出的异常。

当保护代码抛出异常后,程序将跳出
try
块(即使在另一个函数域中),并在
catch
块中寻找关于该异常的处理办法,
Ex e
中Ex即抛出异常的类型,e即处理异常中对异常的称呼(类似函数的参数)

实例

#include<iostream>
using namespace std;
template<class t>
t divide(t a,t b){
    if(b==0) throw"Devided by zero!";
    return a/b;
}
int main(){
    try{
        cout<<divide(10,5)<<endl
            <<divide(10,0)<<endl
            <<divide(18,2)<<endl;
    }
    catch(const char* err){
        cerr<<err<<endl;//std::cerr标准错误流异常输出
    }
    return 0;
}
2
Devided by zero!

不难看出,当
try
块中抛出异常后,程序将第一时间退出保护代码,后面的语句不会被执行。

标准异常

C++提供了一系列标准异常,在

中,实质是一堆相互继承的父子关系类,关系如图:(
std
后要加俩
:

异常 描述

std::exception 该异常是所有标准 C++ 异常的父类。

std::bad_alloc 该异常可以通过 new 抛出。

std::bad_cast 该异常可以通过 dynamic_cast 抛出。

std::bad_exception 这在处理 C++ 程序中无法预期的异常时非常有用。

std::bad_typeid 该异常可以通过 typeid 抛出。

std::logic_error 理论上可以通过读取代码来检测到的异常。

std::domain_error 当使用了一个无效的数学域时,会抛出该异常。

std::invalid_argument 当使用了无效的参数时,会抛出该异常。

std::length_error 当创建了太长的 std::string 时,会抛出该异常。

std::out_of_range 该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator。

std::runtime_error 理论上不可以通过读取代码来检测到的异常。

std::overflow_error 当发生数学上溢时,会抛出该异常。

std::range_error 当尝试存储超出范围的值时,会抛出该异常。

std::underflow_error 当发生数学下溢时,会抛出该异常。

重载异常

你可以通过重载继承
exception
父异常类来创建自己的异常:

#include<iostream>
#include<exception>
using namespace std;
class myexception 
    : public exception
{
public:
    const char* what() const throw() {
        return "Exception : Myexception\n";
    }
};
int main() {
    try {
        throw myexception();
    }
    catch (myexception mye) {
        cout << "Exception caught!\n"
            << mye.what();
    }
    return 0;
}
Exception caught!
Exception : Myexception

一行一行看,

首先:

class myexception : public exception { public:...

表示
public
继承标准库异常类,定义类
myexception

const char * what() const throw()

这一句是关键,
what()
是异常类提供的公共方法,且被所有子异常类重载:

//<exception>
class exception{...
public:...
    ... virtual const char * what() const {...} 
}

可以看到,在标准父异常类中,
what()
被定义为虚函数,因此你才能随意重载它。
what()
函数的标准是没有参数且返回值为C语言风字符串(即
const char *

从左往右看:

  • const char *
    : 返回类型是字符串。

  • what
    : 函数名。

  • ()
    : 参数列表,均为空。

  • const
    : 声明函数无法改变变量。

  • throw()
    : 异常规格说明,表示函数无法抛出任何异常。

看到
main()
,在
try
块里抛出了一个
myexception()

...
throw myexception();
...

相当于调用了myexception类的默认构造函数(没有定义构造函数,系统会自己创建一个),即创建了一个myexception对象并抛出。可以在
myexception
类中定义构造函数:

class myexception{
public:
    ...
    myexception(){cout<<"build func used!\n";}
};
...

则输出会为:

build func used!
Exception caught!
Exception : Myexception

因此在
catch()
块中捕捉了这个myexception对象并调用
what()
方法。

异常规格说明符

  • 见异常规格说明符
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号