C/C++相对论——C++中为什么要使用异常?
C++中为什么要使用异常?
很多人也许知道C++中的异常机制,很多人也许不知道。很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它。
对于C语言,使用正常的if-else即是很好的选择,而在C++中,如果使用了面向对象的编程,最好还是使用Exception机制。这主要设计对象能否正确的析构的问题。
C中的出错跳转setjmp和longjmp
C语言中常用的用于处理异常的方法。它不像abort或者assert或者exit那样直接退出,也不像goto语句仅仅局限在函数内部。
它是用于一种长跳转的方式。可以从一个函数跳到这个函数上层的调用函数中。
举个例子
- 函数 A 中调用了
setjmp设置了一个跳转位,然后函数A调用了函数B。 - 函数 B 中调用了
longjmp,那么会使得程序条到 函数 A中调用setjmp的位置继续执行。
这不是本文的重点。
使用setjmp和longjmp最大的缺点是可能会跳过某些对象的构造或者析构。
还有,在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++中使用setjmp和longjmp造成的不良后果
我们先看代码
无法正常析构对象的代码
#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++中为什么要使用异常?的更多相关文章
- C/C++相对论——C++中为什么要使用异常(跳转语句会造成对象没有被析构)
C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...
- 页面打开 抛出w3wp.exe 中发生未处理异常
页面打开 抛出w3wp.exe 中发生未处理异常
- Ionic2中腾讯Bugly异常捕获以及上报
Ionic2混合开发,入坑系列:Ionic2中腾讯Bugly异常捕获以及上报 1.Ionic2中处理全局异常,直接继承IonicErrorHandler即可,代码如下 import { IonicEr ...
- (转)C#中的那些全局异常捕获
C#中的那些全局异常捕获(原文链接:http://www.cnblogs.com/taomylife/p/4528179.html) 1.WPF全局捕获异常 public partia ...
- Erlang中一些错误或者异常的标识
erlang中错误大体分为四种: 1. 编译错误 2. 逻辑错误 3. 运行时错误 4. 用户代码生成的错误 编译错误,主要是编译器检测出的代码语法错误 逻辑错误,是指程序没有完成预 ...
- 1-hadoop中遇到的各种异常
本贴记录学习hadoop中遇到的各种异常, 包括推荐系统分类下的和本分类下的, 持续更新 1, 搭建ha时, active和standy之间不能自由切换 经检查, 配置文件错误, 私钥配置 root ...
- python怎样在一行中捕获多个异常
所属网站分类: python基础 > 异常处理 作者:浮沉 链接:http://www.pythonheidong.com/blog/article/71/ 来源:python黑洞网,专注pyt ...
- WIN7中 HttpListener 拒绝访问 异常解决 C#
WIN7中 HttpListener 拒绝访问 异常解决 C# http://www.cnblogs.com/cmdszh/archive/2012/08/16/httplistener.html ...
- JAVA 7新特性——在单个catch代码块中捕获多个异常,以及用升级版的类型检查重新抛出异常
在Java 7中,catch代码块得到了升级,用以在单个catch块中处理多个异常.如果你要捕获多个异常并且它们包含相似的代码,使用这一特性将会减少代码重复度.下面用一个例子来理解. Java 7之前 ...
随机推荐
- 自然语言20_The corpora with NLTK
QQ:231469242 欢迎喜欢nltk朋友交流 https://www.pythonprogramming.net/nltk-corpus-corpora-tutorial/?completed= ...
- 从零开始HTML(一 2016/10/17)
就是准备跟着霹雳猿教程过一遍HTML啦,边看边记录更便于理解记忆吧~ 1.属性 HTML 标签可以拥有属性.属性提供了有关 HTML 元素的更多的信息.属性总是以名称/值对的形式出现,比如:name= ...
- yum安装指定(特定)版本(旧版本)软件包的方法
在命令行里输入: yum list SDL 注意这里类库的名字是区别大小写的. 参考 http://www.dabu.info/yum-install-specific-version-old-pac ...
- JavaWeb学习总结(三)——Tomcat服务器学习和使用(二) 包含https 非对称秘钥 NB
JavaWeb学习总结(三)--Tomcat服务器学习和使用(二) 一.打包JavaWeb应用 在Java中,使用"jar"命令来对将JavaWeb应用打包成一个War包,jar命 ...
- svn强制解锁的几种做法
标签: svn强制解锁 2013-12-16 17:40 12953人阅读 评论(0) 收藏 举报 分类: SoftwareProject(23) 版权声明:本文为博主原创文章,未经博主允许不得转 ...
- asp.net core 中的MD5加密
尝试了很长时间,但是一直报core 5 不可用,当时就崩溃了. 但是偶然的机会 我添加了Microsoft.AspNet.Identity 之后.MD5就好用了. 估计是这个报实现了core5下的MD ...
- winScp上传文件时,如何过滤制定文件
在用winScp上传文件时,有些文件不想上传到服务器上.怎么办呢? 比如我希望过滤.svn .git文件和目录怎么操作呢? 第一步:在菜单上选中选项,点击选项. 第二步,点击传输->编辑 第三步 ...
- [译]git push
push就是把你本地仓储的commit传到远程仓储中去. 用法 git push <remote> <branch> push指定的分支到<remote>中去. ...
- Java-开启Java之路
.NET还是我的最爱··· 准备学习下底层知识,为Java打打基础, 然后开始正式学习Java, 也算是曲线救国了, Go,Go,Go ... 二〇一六年十一月十日 18:09:54
- spring配置文件详解--真的蛮详细
spring配置文件详解--真的蛮详细 转自: http://book.51cto.com/art/201004/193743.htm 此处详细的为我们讲解了spring2.5的实现原理,感觉非常 ...