C++标准异常库

一 标准异常类的成员:

① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、和赋值操作符重载。

② logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述

③ 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息。

1.1 标准异常类的具体描述:

异常名称

描述

exception

所有标准异常类的父类

bad_alloc

当operator new and operator new[],请求分配内存失败时

bad_exception

这是个特殊的异常,如果函数的异常抛出列表里声明了bad_exception异常,当函数内部抛出了异常抛出列表中没有的异常,这是调用的unexpected函数中若抛出异常,不论什么类型,都会被替换为bad_exception类型

bad_typeid

使用typeid操作符,操作一个NULL指针,而该指针是带有虚函数的类,这时抛出bad_typeid异常

bad_cast

使用dynamic_cast转换引用失败的时候

ios_base::failure

io操作过程出现错误

logic_error

逻辑错误,可以在运行前检测的错误

runtime_error

运行时错误,仅在运行时才可以检测的错误

 1.2 logic_error的子类:

异常名称

描述

length_error

试图生成一个超出该类型最大长度的对象时,例如vector的resize操作

domain_error

参数的值域错误,主要用在数学函数中。例如使用一个负值调用只能操作非负数的函数

out_of_range

超出有效范围

invalid_argument

参数不合适。在标准库中,当利用string对象构造bitset时,而string中的字符不是’0’或’1’的时候,抛出该异常

1.3 runtime_error的子类:

异常名称

描述

range_error

计算结果超出了有意义的值域范围

overflow_error

算术计算上溢

underflow_error

算术计算下溢

invalid_argument

参数不合适。在标准库中,当利用string对象构造bitset时,而string中的字符不是’0’或’1’的时候,抛出该异常

示例代码:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>   
using namespace std;
#include <stdexcept>   // 标准异常

class num_1
{
    public:
        int age;

        num_1(int age)
        {
            if(age<0 || age>150)
            {
                throw length_error("年龄有错误");   
            } 
        }
};

int main(void)
{
    try
    {
        num_1 p1(1112);
    }
    catch(exception &p2)
    {
        cout << "类型异常,异常类为:" << p2.what() << endl;
    }
    return 0;
}

        在代码中,定义了一个类num_1,其中有一个构造函数,用于判断年龄是否符合要求,并抛出标准异常length_error。在主函数中,通过使用try-catch语句来捕获并处理异常。如果捕获到异常,会输出异常类的信息。通过这种方式可以处理并控制程序中的异常情况。

二 自己写一个异常类

2.1 为什么自己写异常类

① 标准库中的异常是有限的;

② 在自己的异常类中,可以添加自己的信息。(标准库中的异常类值允许设置一个用来描述异常的字符串)。

2.2 如何编写自己的异常类?

① 建议自己的异常类要继承标准异常类。因为C++中可以抛出任何类型的异常,所以我们的异常类可以不继承自标准异常,但是这样可能会导致程序混乱,尤其是当我们多人协同开发时。

② 当继承标准异常类时,应该重载父类的what函数。

2.3 异常类的编写

2.3.1 多态

        因为我们自己编写的异常类要继承自 exception 这个标准异常类,所以我们应该有一种思路就是使用多态来扩展,多态的好处就是不影响原基类的情况下进行安全扩展。

         我们来到 exception 类的定义:

 virtual const char*
    what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;

        可以看到标准异常类也为多态做好了准备,做了一个virtual的虚函数。注意这里返回的是char* 类型的数组。

2.3.2 异常类的编写

        第一步先写一个继承类,继承自exception。

代码如下:

class num_1:public exception   //自己写的异常类
{
    private:
        string msg;

    public:
        num_1(string msg)
        {
            this->msg = msg;
        }
        virtual const char *what() // 记得这里的返回值是char*
        {
            return this->msg.c_str();   // .c_str()作用是类型转换,即string——>char*
        }
};

        第二步做了一个普通的类,并在异常处使用 throw 抛出异常类 num_1。

代码如下:

class num_2      //普通类,进行年龄判断
{
    public:
        int age;

        num_2(int age)
        {
            if(age<0 || age>160)
            {
                if(age<0)
                {
                    throw num_1("年龄小于0,异常");   //抛异常
                }
                else
                {
                    throw num_1("年龄大于160,异常");  //抛异常
                }
               
            }
            else
            {
                this->age = age;
            }
        }
};

        第三步,在 main 函数中进行。

代码如下:

try
    {
        num_2 p1(180);
    }
    catch (exception &e) // 相当于exception &e = num_1("年龄大于160,异常")  符合多态条件
    {
        cout << e.what() << endl;
    }

 总体代码:

#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <string>
#include<iomanip>
#include<fstream>  //头文件流
#include<vector>
using namespace std;


class num_1:public exception   //自己写的异常类
{
    private:
        string msg;

    public:
        num_1(string msg)
        {
            this->msg = msg;
        }
        virtual const char *what() // 记得这里的返回值是char*
        {
            return this->msg.c_str();   // .c_str()作用是类型转换,即string——>char*
        }
};

class num_2
{
    public:
        int age;

        num_2(int age)
        {
            if(age<0 || age>160)
            {
                if(age<0)
                {
                    throw num_1("年龄小于0,异常");
                }
                else
                {
                    throw num_1("年龄大于160,异常");
                }
               
            }
            else
            {
                this->age = age;
            }
        }
};

int main(void)
{
    try
    {
        num_2 p1(180);
    }
    catch (num_1 &e) // exception &e = num_1("年龄大于160,异常")
    {
        cout << e.what() << endl;
    }
    return 0;
}

总结

  • 异常类可以通过继承exception类来自定义
  • 异常类可以包含自定义的错误信息,方便在异常处理时输出错误原因
  • 异常类的成员函数what()必须被重写,返回错误信息的char*类型
  • 在异常类的构造函数中,可以通过条件判断来抛出异常,例如判断年龄是否小于0或大于160
  • 在主函数中,可以使用try-catch块来捕获并处理抛出的异常
  • 捕获到的异常对象可以通过引用传递给catch块,然后使用e.what()来输出错误信息

  • 34
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值