深入了解C++异常处理

目录
  • 基本的异常处理
  • 怎么抛出异常
  • 捕获和处理异常
  • 不存在异常的描述 --- 标识性作用    
  • 删减符 ...
  • 异常处理中的传参操作  --- 可以写一个变量进去
  • 可以抛出自己类的对象
  • 标准库当中的异常类
  • 引发标准库中内存申请失败的异常

基本的异常处理

异常处理机制:暂缓问题处理,不在当前函数中处理,在他的调用者中处理(先上车,后补票)

什么是异常:任何东西都可以认为是异常,错误只是异常的一种

异常一旦被抛出,不做处理,如果引发异常,会调用默认abort函数终止程序

捕获和处理异常:

throw 抛出异常: (值是任何类型都可以,只是我们处理异常的一个参照,类似返回值)

try(检查,捕获)和catch(处理异常): 必须是一起出现,并且它们的括号{ }不能省略

tip:   任何东西都可以认为是异常,错误只是异常中的一种---出现一种情况不能让程序正常运行

怎么抛出异常

//求a和b的余数    怎么抛出异常
int division(int a,int b){
    if(b==0)
        throw 0;    //抛出一个值(任意)--->之后处理
    return a/b;
}
void print(int a,int b){

    cout<<division(a,b);
}
int main(){

    print(1,0);

}
/* 把b==0 的情况称为异常,b==0 时代码不成立,会调用默认abort函数终止程序 */

异常一旦被抛出,不做处理,如果引发异常,会调用默认abort函数终止程序 

捕获和处理异常

//try 与catch必须是一起出现,并且他们的括号{}不能省略
try
{
	//正常需要检查是否存在异常的代码
}
catch(类型)     //理解为switch中case语句
{
    //处理是根据抛出数据类型决定如何处理 匹配项 匹配抛出异常的类型
}

//一个try可以对应多个catch
try
{
	//...
}
catch(int)
{

}
catch(double)
{

}
catch(string)
{

}
//catch和if else_if 执行机制是一样的,只能执行一个匹配项

小知识:

  • 对try{ }   catch(){ } 的理解:在当前位置引发异常,直接从这个位置跳到catch的位置执行catch的代码 --- 类似switch case 语句
  • catch中int和char不会做转换
  • 写两个相同的类型不被允许,哪段代码先引发异常就先调用catch
int division(int a,int b){
    if(b==0)
        throw 0;
    return a/b;
}
void print(int a,int b){

    cout<<division(a,b);
}
int main(){

    try
    {
        print(1,0);     //检查异常
        cout<<"别的代码"<<endl;    //这一句不会运行,会直接跳到catch
    }
    catch(int)                    //抛出的是int类型,捕获int类型
    {
        cout<<"除数不能为0"<<endl;
    }
}

程序能抛出(存在)多个异常,但是只能同时处理1个异常,不能同时引发多个异常

不存在异常的描述 --- 标识性作用    

  • throw ()
  • noexcept
//某个函数不存在异常,在某个函数后面用throw() 描述,表示它不存在异常
void  print() throw()
{
	cout << "当前函数不存在抛出异常操作" << endl;
}
void printData() noexcept
{
	cout << "c++新标准中的关键字: 不存在抛出异常操作" << endl;
	//throw 0;  一旦说明没有异常操作,就不能抛出
}

删减符 ...

任何类型的异常都捕获    不管抛出啥,在哪里抛出的,只要引发异常都可以捕获到

catch(...)
{

    cout <<"捕获任何类型的异常"<< endl;
}

异常处理中的传参操作  --- 可以写一个变量进去

catch(int a)/* 隐藏了一个传参操作 可以传任何类型,包括自定义类型都可以 */

注意c++中string的处理    /* string类型与const char* 类型区别 */

代码解析:

对  通过抛出字符串,隐藏了一个传参操作  的理解

int divisor(int a, int b)
{
	if (b == 0)
		throw string("除数不能为0");
	return a / b;
}

int main()
{
	try
	{
		divisor(1, 0);
	}
	catch (string str)    //把throw的内容赋值给str    str="除数不能为0"
	{
		cout << str << endl;
	}
}

注意string类型与const char* 类型区别  --- 出现类型不匹配,c++对传参类型要求更严格

int divisor(int a, int b)
{
	if (b == 0)
		throw "除数不能为0";    //抛出异常  解析为char* 类型 写catch时不能直接当作string
	if(b==1)
		throw "除数不能为1";    /* 不同问题的抛出,不能用固定类型(int、char...), 可以选择
                                  抛出不同字符串处理 string1,string2,string3... 通过传
                                  参的方式去描述问题 */
	if(b==2)
		throw string("除数不能为2");  //需构造无名参数作捕获对象处理--->需要自己触发
	return a / b;
}

int main()
{
	try
	{
		divisor(1, 0);       //直接触发异常
	}
	catch (const char* str)  //抛出的是char* 类型,不能当作string
	{
		cout << str << endl;
	}
	try
	{
		divisor(1, 2);
	}
	catch (string str)    //如果要捕获string类型,需要自己构造一个string对象返回
	{
		cout << str << endl;    //直接输出str
	}
}

可以抛出自己类的对象

class Error
{
public:
	Error(const char* str = "未知错误") :str(str) {}
	const char* what()const
	{
		return str.c_str();
	}
protected:
	string str;
};

void insertArray(int array[], int* curNum, int posData,int maxLength)
{
	if (*curNum >= maxLength)  //3>=3
	{
		throw  Error("数组下标溢出!");
	}
	//0 1 2
	array[*curNum] = posData;  //array[3]=3
	(*curNum)++;
}

int main(){

    try
	{
		int array[3] = { 0,0,0 };
		int curNum = 0;
		for (int i = 0; i < 4; i++)
		{
			insertArray(array, &curNum, i, 3);
		}
	}
	catch (Error str)
	{
		cout << str.what() << endl;
	}

    return 0;
}

标准库当中的异常类

 #include<exception>    //父类(基类)

子类很多,子类描述的问题不同而已

例子: const char* _ptr; 一个数据成员,用于描述标准库当中异常的字符串,用字符指针存放那个字符串

what( )方法  用于返回数据成员的        1.虚函数        2.不存在异常

return _ptr ? _ptr : "unknow";判断char* 类型的指针是不是为空,不等于空,返回你描述的错误,等于空(由于没有传参),返回未知错误"unknow"

引发标准库中内存申请失败的异常

发现代码出现abort( )错误,可以通过这种方式找到,这里是针对内存申请失败做了单一处理,如果不做处理,会直接调用abort函数终止程序

#include <exception>
#include <iostream>
using namespace std;
class Exception
{
public:
	Exception(const char* ptr="UNKNOW") :ptr(const_cast<char*>(ptr)){} /*构造函数 干掉
                                                                         常属性*/
	virtual const char* what() const    //父类是虚函数 且不存在异常
	{
		return ptr;
	}
protected:
	char* ptr;
};
//子类继承父类
class Bad_alloc :public Exception
{
public:
	Bad_alloc(const char* _Message = "bad exception") :Exception(_Message) {} /*调用父类
                                                           的构造函数抛出bad exception*/
protected:
};
//子类继承父类    调用父类构造函数
class Run_time :public Exception
{
public:
	Run_time(const char* _Message = "run_time error") :Exception(_Message) {}
protected:
};

int main()
{
	try
	{
		while (1)
		{
			int* p = new int[1024*1024*10];//一直做内存申请,不做释放,最后一定会内存申请失败
		}
	}
	catch (bad_alloc& object) /* 内存申请失败,调用bad_alloc 标准库中的异常,创建一个对象接收一
                                 下,子类中的what()方法调用父类中的what()方法打印 */
    {

		cout << object.what() << endl;
	}
	return 0;
}
/*输出*/

bad allocation    //调用时抛出 bad allocation 是子类对象调用继承下来的what()方法

//一般写代码出现莫名的中断,原因是不做异常处理,引发了abort函数中断程序,一般这种错误都是特殊错误

标准库中传两个参数起到标识作用,由于:引发了不同的错误,不同错误对应了不同的错误编码 对这些错误有特定的描述 ---> 工具 ---> 错误查找 ---> 输入错误编码

值:3

错误信息:系统找不到指定的路径 

以上就是深入了解C++异常处理的详细内容,更多关于C++异常处理的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++学习笔记之浅谈异常处理

    异常处理主要是针对能通过编译但是运行是在某个特定条件下会出现异常,程序崩溃,结果出错.来进行的东西 C++处理异常的机制是由3个部分组成的,即检查(try).抛出(throw)和捕捉(catch).把需要检查的语句放在try块中,throw用来当出现异常时发出一个异常信息,而catch则用来捕捉异常信息,如果捕捉到了异常信息,就处理它. try {被检查的语句} catch(异常信息类型 [变量名]) {进行异常处理的语句} 粘一个简单的异常处理的题: 如果三角形满足三角形内角和大于第三边才会有

  • C++的异常处理一篇带你了解

    目录 一.背景 二.C++ 异常处理 三.抛出异常与捕获异常 四.catch(...)的作用 总结 一.背景 程序运行时常会碰到一些异常情况,例如: 做除法的时候除数为 0: 用 new 运算符动态分配空间时,空间不够导致无法分配: 访问数组元素时,下标越界:打开文件读取时,文件不存在. 这些异常情况,如果不能发现并加以处理,很可能会导致程序崩溃. 所谓"处理",可以是给出错误提示信息,然后让程序沿一条不会出错的路径继续执行:也可能是不得不结束程序,但在结束前做一些必要的工作,如将内存

  • C/C++中异常处理详解及其作用介绍

    目录 概述 异常处理 异常处理机制 函数声明指定异常 练习 案例一 案例二 概述 作为一名专业写 Bug, 编程一天改 bug 一周的程序媛. 学会异常处理是非常重要的. 我们不仅要考虑没有错误的理想情况, 更要考虑存在错误时的情况. Debug 可以帮助我们尽快发现错误, 消除错误. 错误类别: 语法错误 运行错误 逻辑错误 异常处理 设计程序时, 事先分析程序运行时可能出现的各种意外情况, 定制出相应的处理方法. 异常处理指对运行时出现的差错以及其他例外情况的处理. 没有异常处理程序时, 运

  • C++异常捕捉与处理的深入讲解

    前言 在阅读别人开发的项目中,也许你会经常看到了多处使用异常的代码,也许你也很少遇见使用异常处理的代码.那在什么时候该使用异常,又在什么时候不该使用异常呢?在学习完异常基本概念和语法之后,后面会有讲解. (1)异常抛出和捕捉语句 //1.抛出异常 throw 异常对象 //2.异常捕捉 try{ 可能会发生异常的代码 }catch(异常对象){ 异常处理代码 } throw子句:throw 子句用于抛出异常,被抛出的异常可以是C++的内置类型(例如: throw int(1);),也可以是自定义

  • 详解C++异常处理(try catch throw)完全攻略

    程序运行时常会碰到一些异常情况,例如: 做除法的时候除数为 0: 用户输入年龄时输入了一个负数: 用 new 运算符动态分配空间时,空间不够导致无法分配: 访问数组元素时,下标越界:打开文件读取时,文件不存在. 这些异常情况,如果不能发现并加以处理,很可能会导致程序崩溃. 所谓"处理",可以是给出错误提示信息,然后让程序沿一条不会出错的路径继续执行:也可能是不得不结束程序,但在结束前做一些必要的工作,如将内存中的数据写入文件.关闭打开的文件.释放动态分配的内存空间等. 一发现异常情况就

  • C++异常处理入门(try和catch)

    目录 捕获异常 发生异常的位置 开发程序是一项"烧脑"的工作,程序员不但要经过长期的知识学习和思维训练,还要做到一丝不苟,注意每一个细节和边界.即使这样,也不能防止程序出错. 专家指出,长期作息不规律 + 用脑过度的危害很大,可能会诱发神经衰弱.失眠等疾病.我就是受害者之一,曾被失眠困扰了好几年,不但入睡困难,还容易早醒.程序员要注意劳逸结合,多去健身房,多跑步,多打球,多陪女朋友旅游等,千万不要熬夜,以为深夜写代码效率高,这样会透支年轻的身体. 程序的错误大致可以分为三种,分别是语法

  • 举例说明自定义C++异常处理的实例

    举例说明自定义C++异常处理的实例 例1:自定义一个继承自excepton的异常类myException C++标准中,定义在<stdexcept>中的任何异常类都派生自exception Class,本例也只是简单地由exception继承,在try段抛出一个异常并捕捉.代码如下: /*++ test.cpp version:1.0 decript:define a exception class named myException derived from base class excep

  • Asp.net Mvc 身份验证、异常处理、权限验证(拦截器)实现代码

    1.用户登录 验证用户是否登录成功步骤直接忽略,用户登录成功后怎么保存当前用户登录信息(session,cookie),本文介绍的是身份验证(其实就是基于cookie)的,下面看看代码. 引入命名空间 using System.Web.Security; 复制代码 代码如下: Users ModelUser = new Users() { ID = 10000, Name = UserName, UserName = UserName, PassWord = PassWord, Roles =

  • PHP 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法

    异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程.这种情况称为异常. PHP 5 添加了类似于其它语言的异常处理模块.在 PHP 代码中所产生的异常可被 throw 语句抛出并被 catch 语句捕获.需要进行异常处理的代码都必须放入 try 代码块内,以便捕获可能存在的异常.每一个 try 至少要有一个与之对应的 catch.使用多个 catch 可以捕获不同的类所产生的异常.当 try 代码块不再抛出异常或者找不到 catch 能匹配所抛出的异常时,PHP 代码就会在跳转到最后一

  • 深入理解golang的异常处理机制

    前言 众所周知在java或php等很多面向对象的语言中, 异常处理是依靠throw.catch来进行的.在go语言中,panic和recover函数在作用层面分别对等throw和catch语句,当然也存在不同之处.下面话不多说,来一起看看详细的介绍吧. 从设计层面来看,panic和recover函数适用于那些真正的异常(例如整数除0),而throw catch finally机制常常被用来处理一些业务层面的自定义异常.因此在go语言中,panic和recover要慎用. 上述两种异常机制的使用中

  • 浅谈NodeJs之数据库异常处理

    本文介绍了NodeJs之数据库异常处理,分享给大家,具体如下: NodeJs版本:4.4.4 数据库链接错误 使用nodejs处理异常最麻烦不过,这里我抛开nodejs提供的domain和一些第三方库专门处理的东西.操作数据库是我们常用的功能.通过回调,我们这里会有很多err出没. 如下: var pool = require('../db.js'); var runtimeLog = require('../log.js').getLogger('runlog'); var Promise =

  • 详解React 16 中的异常处理

    详解React 16 中的异常处理 异常处理 在 React 15.x 及之前的版本中,组件内的异常有可能会影响到 React 的内部状态,进而导致下一轮渲染时出现未知错误.这些组件内的异常往往也是由应用代码本身抛出,在之前版本的 React 更多的是交托给了开发者处理,而没有提供较好地组件内优雅处理这些异常的方式.在 React 16.x 版本中,引入了所谓 Error Boundary 的概念,从而保证了发生在 UI 层的错误不会连锁导致整个应用程序崩溃:未被任何异常边界捕获的异常可能会导致

  • c++异常处理机制示例及详细讲解

    这两天我写了一个测试c++异常处理机制的例子,感觉有很好的示范作用,在此贴出来,给c++异常处理的初学者入门.本文后附有c++异常的知识普及,有兴趣者也可以看看. 下面的代码直接贴到你的console工程中,可以运行调试看看效果,并分析c++的异常机制. 复制代码 代码如下: #include "stdafx.h" #include<stdlib.h> #include<crtdbg.h> #include <iostream> // 内存泄露检测机

  • C++中的异常处理机制详解

    异常处理 增强错误恢复能力是提高代码健壮性的最有力的途径之一,C语言中采用的错误处理方法被认为是紧耦合的,函数的使用者必须在非常靠近函数调用的地方编写错误处理代码,这样会使得其变得笨拙和难以使用.C++中引入了异常处理机制,这是C++的主要特征之一,是考虑问题和处理错误的一种更好的方式.使用错误处理可以带来一些优点,如下: 错误处理代码的编写不再冗长乏味,并且不再和正常的代码混合在一起,程序员只需要编写希望产生的代码,然后在后面某个单独的区段里编写处理错误的嗲吗.多次调用同一个函数,则只需要某个

  • C++中异常处理的基本思想及throw语句抛出异常的使用

    异常处理基本思想 C++的异常处理的基本思想大致可以概括为传统错误处理机制.通过函数返回值来处理错误. 1)C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理.上层调用者可以再适当的位置设计对不同类型异常的处理. 2)异常是专门针对抽象编程中的一系列错误处理的,C++中不能借助函数机制,因为栈结构的本质是先进后出,依次访问,无法进行跳跃,但错误处理的特征却是遇到错误信息就想要转到若干级之上进行重新尝试,如图 3)异常超

  • C++的try块与异常处理及调试技术实例解析

    本文以示例形式简述了C++ try块的异常处理与调试技术,有助于读者复习并加深对try块的了解. 一.格式: 抛出异常throw 异常类型例如throw runtime_error("Data must refer to same ISBN"); try{ program-statements }catch(exception-specifier) { handler-statement; }catch(exception-specifier) { handler-statement;

随机推荐