c++中的异常--1(基本概念, c语言中处理异常,c++中处理异常,异常的基本使用,栈解旋)

异常基本概念

异常处理就是处理程序中的错误,所谓错误是指在程序运行的过程中发生的一些异常事件(如:除0退出,数组下标越界,所要读取的文件不存在,空指针,内存不足等等)

c语言中处理异常

两种方法:

  1. 使用整形的返回值标识错误;

  2. 使用errno宏(可以简单的理解为一个全局整形变量)去记录错误,当然c++中仍然可以用这两种方法的。

  3. 这两种方法最大的缺陷就是会出现不一致问题,例如有些函数返回1表示成功,有些则返回0表示成功

  4. 还有一个缺点就是函数的返回值只有一个,你通过函数的返回值表示错误代码,那么函数就不能返回其他的值。当然,你也可以通过指针或者c++的引用来返回另外的值,但是这样可能会令你的程序比较难懂

c++中处理异常

  1. 函数的返回值可以忽略,但异常不可忽略,如果程序出现异常,但是没有被捕获,程序就会终止,这多少会促使程序员开发出来的程序更健壮一点,而如果使用C语言的errot宏或者函数的返回值,调用者都有可能忘记检查,从而没有对错进行处理,结果造成程序员莫名其妙的终止或出现错误的结果
  2. 整型返回值没有任何语义信息,而异常却包含语义信息,有时你从类名就能狗体现出来
  3. 整型返回值缺乏相关的上下文信息,异常作为一个类,可以拥有自己的成员,这些成员可以传递足够的信息
  4. 异常处理可以在调用跳级。这是一个代码编写时的问题:假设在有多个函数的调用栈中出现某个错误,使用整型返回码要求你在每一级函数中都要进行处理,而使用异常处理的栈展开机制,只需要在一处进行处理就可以,不需要每级函数都处理

异常的基本使用

  1. try试图执行try{}中的内容

  2. 在可能出现异常的地方 抛出异常 throw

  3. try下面catch捕获异常

  4. catch(捕获类型)...代表 所有其他类型

  5. 如果不想处理异常,继续向上抛出throw

  6. 如果没有任何处理异常的地方,那么成员调用terminate函数中断

  7. 自定义异常类,可以抛出自定义的对象

    #include<iostream>
    
    using namespace std;
    
    
    class myException  //自定义异常类
    {
    public:
    	void printError()
    	{
    		cout << "自定义的异常" << endl;
    	}
    };
    
    
    int myDevide(int a, int b)
    {
    	if (b == 0)
    	{
    		//如果b是异常,抛出异常
    		//return -1;
    		//throw - 1; 抛出int类型异常
    		//throw 3.14;//抛出double类型异常   异常必须处理
    		//throw 'a';
    		throw myException(); //匿名对象
    	}
    	return a / b;
    }
    
    void test01()
    
    {
    	int a = 10;
    	int b = 0;
    	//int ret = myDevide(a, b);//早期如果返回-1 无法区分到底是结果还是异常
    
    	//c++中异常处理
    	try
    	{
    		myDevide(a, b);
    	}
    	catch (int)//捕获异常
    	{
    		cout << "int 类型异常捕获" << endl;
    	}
    	catch (double)
    	{
    		//如果不想处理这个异常,可以向继续向上抛出
    		throw;
    		cout << "double类型异常捕获" << endl;
    	}
    
    	catch (myException e)
    	{
    		e.printError();
    	}
    
    	catch (...)
    	{
    		cout << "其他异常类型捕获" << endl;
    	}
    
    }
    
    
    
    
    
    int main()
    {
    	try
    	{
    		test01();
    	}
    	catch (double) //如果异常都没处理,那么成员terminate函数,使程序中断
    	{
    		cout << "main函数中double类型异常捕获" << endl;
    	}
    	catch (...)
    	{
    		cout << "main函数中其他异常类型捕获" << endl;
    	}
    
    	//test01();
    	system("pause");
    	return 0;
    }
    

总结:

  1. 若有异常则通过throw操作创建一个异常对象并抛出

  2. 将可能抛出异常的程序投放到try块之中

  3. 如果在try段执行期间没有引起异常,那么跟在try后面的catch字句就不会执行

  4. catch子句会根据出现的先后顺序被检查,匹配的catch语句捕获并处理异常(或继续抛出异常)

  5. 如果匹配的处理来找到,则运行函数terminate将自动被调用,其缺省功能调用abort终止程序

  6. 处理不了的异常,可以在catch的最后一个分支,使用throw,向上抛

  7. c++异常处理使得异常的引发和异常的处理不必在一个函数中,这样底层可以着重解决具体问题,而不必过多的考虑异常的处理,上层调用者可以在适当的位置设计对不同类型异常的处理

     #include<iostream>
     
     using namespace std;
     
     
     class myException  //自定义异常类
     {
     public:
     	void printError()
     	{
     		cout << "自定义的异常" << endl;
     	}
     };
     
     
     int myDevide(int a, int b)
     {
     	if (b == 0)
     	{
     		//如果b是异常,抛出异常
     		//return -1;
     		//throw - 1; 抛出int类型异常
     		//throw 3.14;//抛出double类型异常   异常必须处理
     		//throw 'a';
     		throw myException(); //匿名对象
     	}
     	return a / b;
     }
     
     void test01()
     
     {
     	int a = 10;
     	int b = 0;
     	//int ret = myDevide(a, b);//早期如果返回-1 无法区分到底是结果还是异常
     
     	//c++中异常处理
     	try
     	{
     		myDevide(a, b);
     	}
     	catch (int)//捕获异常
     	{
     		cout << "int 类型异常捕获" << endl;
     	}
     	catch (double)
     	{
     		//如果不想处理这个异常,可以向继续向上抛出
     		throw;
     		cout << "double类型异常捕获" << endl;
     	}
     
     	catch (myException e)
     	{
     		e.printError();
     	}
     
     	catch (...)
     	{
     		cout << "其他异常类型捕获" << endl;
     	}
     
     }
     
     
     
     
     
     int main()
     {
     	try
     	{
     		test01();
     	}
     	catch (double) //如果异常都没处理,那么成员terminate函数,使程序中断
     	{
     		cout << "main函数中double类型异常捕获" << endl;
     	}
     	catch (...)
     	{
     		cout << "main函数中其他异常类型捕获" << endl;
     	}
     
     	//test01();
     	system("pause");
     	return 0;
     }
    

栈解旋

  1. 从try开始到throw抛出异常之前,所有栈上的对象都会被释放,这个过程称为栈解旋,构造析构顺序相反

  2. 栈上对象构造顺序与析构顺序相反

     class Person
     {
     public:
     	Person()
     	{
     		cout << "Person构造" << endl;
     
     	}
     	~Person()
     	{
     		cout << "Person析构" << endl;
     	}
     };
     
     
     int myDevide(int a, int b)
     {
     	if (b == 0)
     	{
     		//如果b是异常,抛出异常
     		//return -1;
     		//throw - 1; 抛出int类型异常
     		//throw 3.14;//抛出double类型异常   异常必须处理
     		//throw 'a';
     
     
     		//栈解旋
     		//从try开始到throw抛出异常之前,所有栈上的对象都会被释放
     		//这个过程称为栈解旋
     		//构造析构顺序相反
     
     		Person p1;
     		Person p2;
     
     
     
     		throw myException(); //匿名对象
     	}
     	return a / b;
     }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值