C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决不了,再传给其上一级,由其上一级处理。如此逐级上传,直到最高一级还无法处理的话,运行系统会自动调用系统函数terminate.

格式:

try

{

}

catch(...)  //表示任何异常

{

}

如果在catch 中没有调用throw 再次抛出异常,说明该异常在catch中被吞掉,不会再传出调用该函数之外。

throw:

1.throw抛出的永远是对象的拷贝(包括普局部变量、引用,静态变量)。不管该对象离开作用域时是否被析构(堆上变量、静态变量);或者被抛出的对象不会被释放,也会进行拷贝操作,如抛出的对象是静态变量,或者是引用)。

因此和函数传参有区别,函数传引用参数时不需要拷贝。

2.当异常对象被拷贝时,拷贝操作是由对象的拷贝构造函数完成的。该拷贝构造函数是对象的静态类型(static type)所对应类的拷贝构造函数,而不是对象的动态类型(dynamic type)对应类的拷贝构造函数。

class Widget { ... };
class SpecialWidget: public Widget { ... };
void passAndThrowWidget()
{
SpecialWidget localSpecialWidget;
...
Widget& rw = localSpecialWidget; // rw 引用SpecialWidget
throw rw; //它抛出一个类型为Widget
// 的异常
}
这里抛出的异常对象是Widget,即使rw引用的是一个SpecialWidget。因为rw的静态类型(static
type)是Widget,而不是SpecialWidget。

3.

catch (Widget& w) // 捕获Widget异常
{
... // 处理异常
throw; // 重新抛出异常,让它
} // 继续传递
catch (Widget& w) // 捕获Widget异常
{
... // 处理异常
throw w; // 传递被捕获异常的
} // 拷贝
第一个块中重新抛出的是当前异常(current exception),无论它是什么类型。特别是如果这个异常开始就是做为SpecialWidget类型抛出的,那么第一个块中传递出去的还是SpecialWidget异常,即使w的静态类型(static  type)是Widget。这是因为重新抛出异常时没有进行拷贝操作。第二个catch块重新抛出的是新异常,类型总是Widget,因为w的静态类型(static type)是Widget。一般来说,你应该用throw来重新抛出当前的异常,因为这样不会改变被传递出去的异常类型,而且更有效率,因为不用生成一个新拷贝。

个人觉得:throw最好抛出的是对象。

执行throw后,如果在当前函数没有执行catch进行捕捉的话,throw后面的代码就不会被执行,所以在要注意内存泄漏的问题。

就算上一次函数执行了catch捕捉异常,原来的throw之后的代码也不会执行。

所以

1.在构造函数中抛出了异常,该构造函数就不能完整执行完,对象构造不成功。

2.在析构函数中抛出异常,存在内存泄漏。

延伸:函数声明后面加throw()的作用

void fun() throw();      //表示fun函数不允许抛出任何异常,即fun函数是异常安全的。

void fun() throw(...);    //表示fun函数可以抛出任何形式的异常。

void fun() throw(exceptionType);    // 表示fun函数只能抛出exceptionType类型的异常。

catch

1.catch()块接收异常类型不进行隐式类型转换(除了以下2种情况),被调函数则可以进行(例:try抛出的int异常,不会被处理double异常的catch块捕获)。

a.第一种是继承类与基类间的转换

b.一个类型化指针(typed pointer)转变成无类型指针(untyped pointer),所以带有const void* 指针的catch子句能捕获任何类型的指针类型异常。

2.异常传递到 catch 子句中有三种方式:通过指针(by pointer),通过传值(by value)或通过引用(by reference),其中引用最好.

a.通过指针的方式,对静态异常变量catch中不需要delete,但堆上异常变量需要delete,因此较复杂。而且通过指针捕获异常也不符合C++语言本身的规范。

b.通过传值时,需要进行拷贝两次(离开作用域一次,catch接收一次),而且它会产生 slicing problem(切割问题),即派生类的异常对象被做为基类异常对象捕获时,那它的派生类行为就被切掉了(sliced off)。这样的sliced对象实际上是一个基类对象:它们没有派生类的数据成员,而且当本准备调用它们的虚拟函数时,系统解析后调用的却是基类对象的函数。

c.异常变量复制一次,避免了上述所有问题。

延伸:

四个标准的异常

bad_alloc(当operator new(参见条款M8)不能分配足够的内存时,被抛出),

bad_cast(当dynamic_cast针对一个引用(reference)操作失败时,被抛出),

bad_typeid(当dynamic_cast对空指针进行操作时,被抛出)

bad_exception(用于unexpected异常;参见条款M14)――都不是指向对象的指针。

CException是Microsoft基本类库中处理各种异常的基础库。

CException是一个抽象基类,不可构造一个CException对象.

其派生库及描述如下:

CMemoryException

内存不够
CNotSupportedException 请求不支持的操作
CArchiveException 文档指定异常
CFileException 文件指定异常
CResourceException Windows资源未找到或不可创建
COleException OLE异常
CDBException 数据库异常(即基于开放数据库连接的MFC数据库类出现异常)
COleDispatchException OLE发送(自动)异常
CUserException 资源无法找到
CDaoException 数据访问对象异常(即DAO类出现异常)
CInternetException Internet异常(即Internet类出现异常)

1.可以在try{}中手动抛出异常throw/

2.可以使用多个catch来捕捉异常。

3.可以调用GetErrorMessage或ReportError来向用户报告异常的详细情况。

4.如果Catch关键字得到异常,则不会自动删除。需调用delete函数。

CException

构造一个CException对象
Delete 删除一个CException对象
GetErrorMessage 获取异常描述信息
ReportError 在消息框中向用户报告一个错误信息

try

{

}

catch(CException *e)  //

{

e->ReportError();

e->delete();

}

使用的场景有:原则是容易抛出异常地方,如

1.内存操作的,分配、释放、移动

2.序列化读写文件CArchive

3.使用第三方接口读写excel文件。

bad_alloc 是operator new不能满足内存分配请求时抛出的异常类型。

try

{

}

catch(bad_alloc  &e)  //

{

}

try

{

}

catch(std::bad_alloc  &)  //

{

}

c++ 中 try catch throw异常相关推荐

  1. JavaScript中try, catch, throw的用法

    文章出自个人博客https://knightyun.github.io/2019/09/02/js-try,转载请申明. 程序在运行中难免遇到 bug,所以就需要好的调试手段找出问题所在,try, c ...

  2. C++中try/catch/throw的使用

    C++异常是指在程序运行时发生的反常行为,这些行为超出了函数正常功能的范围.当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理.异常提供了一种转移程序控制权的方式.C++异常处理涉及到三个关 ...

  3. java中try...catch处理异常

    public class TryCatchStu {  /*try catch:自己处理异常   *try{   * 可能出现异常的代码   *}catch(异常类名A e){   * 如果出现了异常 ...

  4. 程序中try、throw、catch三者之间的关系

    c++程序中,采用一种专门的结构化处理逻辑的异常处理机制. 1.try语句 try语句块的作用是启动异常处理机制,检测try语句块中程序语句执行时可能出现的异常. try语句块总是与catch一同出现 ...

  5. 5、catch中发生了未知异常,finally代码块如何应对?

    catch中发生了未知异常,finally还会执行么? catch发生了异常,finally还是会执行的,并且是finally执行完成后,才会抛出catch中的异常. 不过catch会吃掉try中抛出 ...

  6. C#中try catch中throw ex和throw方式抛出异常有何不同

    C#中try catch中throw ex和throw方式抛出异常有何不同 参考文章: (1)C#中try catch中throw ex和throw方式抛出异常有何不同 (2)https://www. ...

  7. 22 C#中的异常处理入门 try catch throw

    22 C#中的异常处理入门 try catch throw 参考文章: (1)22 C#中的异常处理入门 try catch throw (2)https://www.cnblogs.com/thin ...

  8. SpringBoot中try/catch异常并回滚事务(自动回滚/手动回滚/部分回滚)

    在Spring官方文档中说到,当Transaction内发生unchecked exception的时候,会自动rollback,但是当Transaction内发生checked exception时 ...

  9. transactionscope 中的异步 处理 异常_协程中的取消和异常 | 异常处理详解

    开发者们通常会在打磨应用的正常功能上花费很多时间,但是当应用出现一些意外情况时,给用户提供合适的体验也同样重要.一方面来讲,对用户来说,目睹应用崩溃是个很糟糕的体验:而另一方面,在用户操作失败时,也必 ...

  10. 第8集析构函数中抛出的异常

    前两篇文章讨论了对象在构造过程中(构造函数)和运行过程中(成员函数)出现异常时的处理情况,本文将讨论最后一种情况,当异常发生在对象的析构销毁过程中时,又会有什么不同呢?主人公阿愚在此可以非常有把握地告 ...

最新文章

  1. 【微信小程序】:实现轮播图3秒滚动
  2. iOS开发——NSArray中的字典排序
  3. 城市需要建什么样的能源数据中心?
  4. 学习记录:CONCAT()
  5. maven添加非官方jar包到本地库
  6. 牛客16429 组合数问题(二维前缀和、杨辉三角)
  7. 接口传值后不起作用_聊一聊 API 接口测试
  8. MySQL抽稀_python安装mysql的依赖包mysql-python操作
  9. linux中java 里面启动 重启 停止jar 的 shell
  10. ADO.NET Entity Framework支持多Provider
  11. js数组操作大全(转)
  12. redis连接数据库进行操作
  13. Show, Control and Tell: A Framework for Generating Controllable and Grounded Captions
  14. 小马快跑win7激活_更快地激活服务人员
  15. python最大公约数计算_Python怎样求得最大公约数
  16. 用零知识证明连接多链宇宙
  17. 使用Electron将html网页转为exe可执行文件(全屏, 遮住任务栏, Esc退出, exe的图标/文件名修改)
  18. Flutter加载大图内存问题处理
  19. 常见文件头 文件幻数
  20. 计算机视觉到底需要学什么?怎么快速入门?

热门文章

  1. Solaris10 swap空间管理
  2. [Google Guava]学习--新集合类型BiMap
  3. mysqludf_json将关系数据以JSON编码
  4. 清空SQL数据库日志
  5. 新建SVN Repository
  6. HTTPModules与HTTPHandler
  7. 解决Required String parameter xxx is not present异常
  8. java new对象_Java中new一个对象是一个怎样的过程?JVM中发生了什么?
  9. 微服务架构实战篇(三):Spring boot2.0 + Mybatis + PageHelper实现增删改查和分页查询功能
  10. 微信小程序-template使用:实现购物车商品数量加减功能