C++中为什么要使用异常?

很多人也许知道C++中的异常机制,很多人也许不知道。很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它。

对于C语言,使用正常的if-else即是很好的选择,而在C++中,如果使用了面向对象的编程,最好还是使用Exception机制。这主要设计对象能否正确的析构的问题。

C中的出错跳转setjmplongjmp

C语言中常用的用于处理异常的方法。它不像abort或者assert或者exit那样直接退出,也不像goto语句仅仅局限在函数内部。
它是用于一种长跳转的方式。可以从一个函数跳到这个函数上层的调用函数中。
举个例子

  1. 函数 A 中调用了setjmp设置了一个跳转位,然后函数A调用了函数B。
  2. 函数 B 中调用了longjmp,那么会使得程序条到 函数 A中调用setjmp的位置继续执行。

这不是本文的重点。

使用setjmplongjmp最大的缺点是可能会跳过某些对象的构造或者析构。
还有,在C中使用goto可以跳过某些变量的定义,但是这不会出什么问题。可以试试下面的代码。注意,是C语言,你要是用C++的编译器来编译,应该是会报错的。

 #include <stdio.h>

 int main(int argc,char** argv)
{
if(argc > ){
goto nodef;
}
int a = ;
nodef:
printf(" a = %d\n",a);
return ;
}

C++中使用setjmplongjmp造成的不良后果

我们先看代码

无法正常析构对象的代码

 #include <iostream>
#include <csetjmp> using std::cout;
using std::endl; class Test{
public:
Test(){ cout<<"Test 构造"<<endl;}
~Test(){cout<<"Test 析构"<<endl;}
}; jmp_buf jbuf; //用于setjmp保存当前相关信息 void calljmp()
{
Test t; //测试能够正确调用析构
cout<<"call longjmp(jbuf,3721)"<<endl;
longjmp(jbuf,);
} int main()
{
int ret=;
if( == (ret=setjmp(jbuf))){
cout<<"call setjmp(jbuf) resuces"<<endl;
calljmp();
}
else{
cout<<"call setjmp(jbuf) failed ret = "<< ret <<endl;
}
}

编译执行看看

可以看到,对象构造了,但是没有正常的调用析构。

 o@o-pc:~/code_/exception$ g++ setjmp.cpp -o setjmp
o@o-pc:~/code_/exception$ ./setjmp
call setjmp(jbuf) resuces
Test 构造
call longjmp(jbuf,)
call setjmp(jbuf) failed ret =

C++中使用异常处理的情况

C++中使用异常机制的好处之一,就是能够正确的去析构对象。

使用了异常处理机制的代码

 #include <iostream>
#include <csetjmp> using std::cout;
using std::endl; class Test{
public:
Test(){ cout<<"Test 构造"<<endl;}
~Test(){cout<<"Test 析构"<<endl;}
}; jmp_buf jbuf; //用于setjmp保存当前相关信息 void calljmp()
{
Test t; //测试能够正确调用析构
cout<<"call longjmp(jbuf,3721)"<<endl;
//longjmp(jbuf,3721);
throw ;
} int main()
{
try{
cout<<"调用calljmp 尝试抛出异常"<<endl;
calljmp();
}catch(int t){
cout<<"捕获到异常值:"<<t<<endl;
}
/*
int ret=0;
if( 0 == (ret=setjmp(jbuf))){
cout<<"call setjmp(jbuf) resuces"<<endl;
calljmp();
}
else{
cout<<"call setjmp(jbuf) failed ret = "<< ret <<endl;
}
*/
}

编译运行试试

可以看到这次正常调用了析构函数

o@o-pc:~/code_/exception$ g++ exception.cpp -o exception
o@o-pc:~/code_/exception$ ./exception
调用calljmp 尝试抛出异常
Test 构造
call longjmp(jbuf,)
Test 析构
捕获到异常值:

C/C++相对论——C++中为什么要使用异常?的更多相关文章

  1. C/C++相对论——C++中为什么要使用异常(跳转语句会造成对象没有被析构)

    C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...

  2. 页面打开 抛出w3wp.exe 中发生未处理异常

    页面打开 抛出w3wp.exe 中发生未处理异常

  3. Ionic2中腾讯Bugly异常捕获以及上报

    Ionic2混合开发,入坑系列:Ionic2中腾讯Bugly异常捕获以及上报 1.Ionic2中处理全局异常,直接继承IonicErrorHandler即可,代码如下 import { IonicEr ...

  4. (转)C#中的那些全局异常捕获

    C#中的那些全局异常捕获(原文链接:http://www.cnblogs.com/taomylife/p/4528179.html)   1.WPF全局捕获异常       public partia ...

  5. Erlang中一些错误或者异常的标识

    erlang中错误大体分为四种: 1. 编译错误    2. 逻辑错误    3. 运行时错误    4. 用户代码生成的错误 编译错误,主要是编译器检测出的代码语法错误 逻辑错误,是指程序没有完成预 ...

  6. 1-hadoop中遇到的各种异常

    本贴记录学习hadoop中遇到的各种异常, 包括推荐系统分类下的和本分类下的, 持续更新 1, 搭建ha时, active和standy之间不能自由切换 经检查, 配置文件错误, 私钥配置 root ...

  7. python怎样在一行中捕获多个异常

    所属网站分类: python基础 > 异常处理 作者:浮沉 链接:http://www.pythonheidong.com/blog/article/71/ 来源:python黑洞网,专注pyt ...

  8. WIN7中 HttpListener 拒绝访问 异常解决 C#

      WIN7中 HttpListener 拒绝访问 异常解决 C# http://www.cnblogs.com/cmdszh/archive/2012/08/16/httplistener.html ...

  9. JAVA 7新特性——在单个catch代码块中捕获多个异常,以及用升级版的类型检查重新抛出异常

    在Java 7中,catch代码块得到了升级,用以在单个catch块中处理多个异常.如果你要捕获多个异常并且它们包含相似的代码,使用这一特性将会减少代码重复度.下面用一个例子来理解. Java 7之前 ...

随机推荐

  1. OC面向对象特性:封装

    概念性知识  1.c语言是面向过程编程:分析解决问题的步骤,实现函数,依次调用  2.oc语言是面向对象编程:分析问题的组成的对象,协调对象间的联系和通信,解决问题  3.#include和#impo ...

  2. header的安全配置指南

    0x00 背景 在统计了Alexa top 100万网站的header安全分析之后(2012年11月 - 2013年3月 - 2013年11月),我们发现其实如何正确的设置一个header并不是一件容 ...

  3. PHP任意文件包含绕过截断新姿势

    前言 此方法是@l3m0n叔叔给我分享的,原文已经发布在90sec 我没有90sec的账号,所以自己实践一下,顺道安利给访问我博客的小伙伴. 适用情况 可以控制协议的情况下,如果%00无法截断包含,可 ...

  4. 【struts2】Result和ResultType

    简单的说,Result是Action执行完后返回的一个字符串,它指示了Action执行完成后,下一个页面在哪里.Result仅仅是个字符串,仅仅是用来指示下一个页面的,那么如何才能够到达下一个页面呢? ...

  5. iOS开发 关于SEL的简单总结

    SEL就是对方法的一种包装.包装的SEL类型数据它对应相应的方法地址,找到方法地址就可以调用方法.在内存中每个类的方法都存储在类对象中,每个方法都有一个与之对应的SEL类型的数据,根据一个SEL数据就 ...

  6. CSS样式表继承详解

    最近在恶补css样式表的基础知识.上次研究了css样式表之冲突问题详解 .这次是对 css 继承 特性的学习. 什么是css 继承?要想了解css样式表的继承,我们先从文档树(HTML DOM)开始. ...

  7. ThinkPHP的四种URL模式 URL_MODEL

    ThinkPHP支持四种URL模式,可以通过设置URL_MODEL参数来定义,包括普通模式.PATHINFO.REWRITE和兼容模式. 普通模式 设置URL_MODEL 为0 采用传统的URL参数模 ...

  8. php开发中怎么获取服务端MAC地址?

    MAC(Media Access Control或者Medium Access Control)地址,意译为媒体访问控制,或称为物理地址.硬件地址,用来定义网络设备的位置.在php中如何获取MAC(M ...

  9. 深入理解Javascript面向对象编程

    深入理解Javascript面向对象编程 阅读目录 一:理解构造函数原型(prototype)机制 二:理解原型域链的概念 三:理解原型继承机制 四:理解使用类继承(继承的更好的方案) 五:建议使用封 ...

  10. 通过Canvas及File API缩放并上传图片完整示例

    <!DOCTYPE html> <html> <head> <title>通过Canvas及File API缩放并上传图片</title> ...