19.1 c++ 异常

文章介绍了C++中的异常处理机制,包括异常的基本概念,如除0溢出、数组下标越界等。强调了C++异常处理优于C语言的方面,如异常包含语义信息。详细阐述了如何抛出和捕获异常,以及栈解旋的过程,即在异常发生时对象的自动析构。此外,还讨论了异常的接口声明,如何限制函数可抛出的异常类型,以及异常变量的生命周期。最后,提到了C++的标准异常类和如何编写自定义异常类。
摘要由CSDN通过智能技术生成

第十九章 异常

19.1 异常的基本概念

遇到错误 抛出异常 捕获异常

异常:是指在程序运行的过程中发生的一些异常事件(如:除0溢出,数组下标越界,所要读取的文件不存在,空指针,内存不足,访问非法内存等等)。(异常是一个类)

c++异常机制相比C语言异常处理的优势?

​ 函数的返回值可以忽略,但异常不可忽略。(忽略异常 程序结束)

​ 整型返回值没有任何语义信息。而异常却包含语义信息,有时你从类名就能体现出来。

19.2 异常的抛出和捕获

19.2.1 异常的抛出和捕获

try
{
	throw 异常值;
}
catch(异常类型1 异常值1)
{
    处理异常的代码1;
}
catch(异常类型2 异常值2)
{
    处理异常的代码2;
}
catch(...)//任何异常都捕获
{
    处理异常的代码3;
}

19.2.2 异常抛出和捕获案例

int ret = 0;
try
{
	//throw 1;
	//throw 'A';
    throw 2.14f;
}
catch(int e) //捕获
{
    cout<<"char 异常值为:"<<e<<endl;
}
catch(char e)//捕获
{
    cout<<"char异常值为:"<<e<<endl;
}
catch(...)//捕获所有异常
{
    cout<<"其他异常值为:"<<endl;
}

19.3 栈解旋

异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反,这一过程称为栈的解旋。

try
{
	Data ob1;
	Data ob2;
	Data ob3;
	throw 1;//抛出异常后 ob3 ob2 ob1 依次自动释放(栈解旋)
}

19.3.1 栈解旋案例

#include <iostream>
using namespace std;

class Data{
public:
   	int a;
public:
    Data(){}
    Data(int a)
    {
        this->a = a;
        cout<<"构造函数"<<a<<endl;
    }
    ~Data()
    {
        cout<<"析构函数"<<a<<endl;
    }
};

int main()
{
    int ret = 0;
    try
    {
        Data ob1(10);
        Data ob2(20);
        Data ob3(30);
        throw 1;
    }
    
    catch(int)//捕获
    {
        cout<<"int异常值为:"<<endl;
    }
    catch(char)//捕获
    {
        cout<<"char异常值为:"<<endl;
    }
    catch(...)//捕获
    {
        cout<<"其他异常值为:"<<endl;
    }
}

19.4 异常的接口声明

异常的接口声明:描述的是 可以抛出哪些类型的异常值

19.4.1 函数默认 可以抛出任何类型的异常(推荐)

void fun01()
{
	//throw 1;
	//throw '1';
	throw "hello";
}

19.4.2 只能抛出特定类型异常

void fun02() throw(int,char)
{
	//throw 1;
	//throw '1';
	throw "hello";//抛出 不能捕获
}

19.4.3 不能抛出任何异常

void fun02() throw()
{
	throw 1;
	//throw '1';
	//throw "hello";//抛出 不能捕获
}

19.5 异常变量的生命周期

class MyException
{
public:
    MyException(){
        cout<<"异常变量构造"<<endl;
    };
    MyException(const MyException & e)
    {
        cout<<"拷贝构造"<<endl;
    }
    ~MyException()
    {
		cout<<"异常变量析构"<<endl;
    }
};

19.5.1 以普通对象 接异常值

在这里插入图片描述

19.5.2 以对象指针 接异常值

在这里插入图片描述

19.5.3 对象引用 接异常值(推荐)

在这里插入图片描述

19.6 异常的多态

//异常基类
class BaseException{
public:
	virtual void printError(){};
};

//空指针异常
class NullPointerException:public BaseException{
public:
	virtual void printError(){
		cout<<"空指针异常!"<<endl;
	}
};
//越界异常
class OutOfRangeException:public BaseException{
public:
    virtual void printError(){
        cout<<"越界异常!"<<endl;
    }
};

void doWork()
{
	//throw NullPointerException();
    throw OutOfRangeException();
}
int main()
{
    try{
        doWork();
    }
    catch (BaseException& ex)//父类引用 可以捕获搭配该父类派生出所有子类的子类
    {
        ex.printError();
    }
}

19.7 c++标准异常

在这里插入图片描述

异常名称描述
exception所有标准异常类的父类
bad_alloc当operator new and operator new[],请求分配内存失败时
bad_exception这是个特殊的异常,如果函数的异常抛出列表声明了badexception异常,当函数内部抛出了异常抛出列表中没有的异常,这是调用的unexpected函数中若抛出异常,不论什么类型,都会被替换为badexception类型
bad_typeid使用typeid操作符,操作一个NULL指针,而该指针是带有虚函数的类,这时抛出bad_typeid异常
bad_cast使用dynamic_cast转换引用失败的时候
ios_base::failureio操作过程出现错误
logic_error逻辑错误,可以在运行前检测的错误
runtime_error运行时错误,仅在运行时才可以检测的错误

logic_error的子类:

异常名称描述
length_error试图生成一个超出该类型最大长度的对象时,例如vector的resize操作。
domain_error参数的值域错误,主要用在数学函数中。例如使用一个负值调用只能操作非负数的函数。
outo/range超出有效范围。
invalid_argument参数不合适。在标准库中,当利用string对象构造bitset时,而string中的字符不是‘0’或‘1’的时候,抛出该异常。

runtime_error的子类

异常名称描述
range_error计算结果超出了有意义的值域范围
overflow_error算术计算下溢
underflow_error算术计算上溢
invalid_argument参数不合适。在标准库中,当利用string对象构造bitset时,而string中的字符不是‘0’或‘1’的时候,抛出该异常。

在这里插入图片描述

19.8 编写自己的异常

基于标准异常基类 编写自己的异常类。

class NewException:public exception
{
private:
    string msg;
public:
    NewException(){}
    NewException(string msg)
    {
        this->msg = msg;
    }
    //重写父类的what
    virtual const char* what() const throw()//防止父类在子类前抛出标准异常
    {
        //将string类转换成char *
        return this->msg.c_str();
    }
    ~NewException(){}
};

int main()
{
	try
	{
		throw NewException("自己的异常");
	}
    catch(exception &e)
    {
        cout<<e.what()<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值