免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: wwwsq
打印 上一主题 下一主题

[C++] 有人会在程序中try catch吗? [复制链接]

论坛徽章:
0
71 [报告]
发表于 2008-08-31 02:46 |只看该作者
原帖由 lgfang 于 2008-8-31 02:26 发表


以下是从c++ 编程语言特别版(真是本好书,有人评价“这才是真正配得上‘c++编程思想'一名的书")摘录的建议:

[8] Throw an exception to indicate failure in a constructor; §14.4.6.
[9] Avoid t ...



理论和实践是有距离的。

比如“Throw an exception to indicate failure in a constructor”,如果这个对象是个全局对象怎么办?
对于“Be sure that every resource acquired in a constructor is released when throwing an exception
in that constructor”,在构造函数里面,压根就不应该出现exception什么的。否则你就要面对一系列诸如8,9,10,11,12,13这样的规则,而实际上没人能够切实做到这些规则。

论坛徽章:
0
72 [报告]
发表于 2008-08-31 02:50 |只看该作者
原帖由 lgfang 于 2008-8-31 02:23 发表

当然是错误处理。
但是错误处理不一定都要抛出异常。我觉的如果当前context知道如何如何处理就处理了,不清楚的话才抛出异常。

以你的例子来讲:假设很不清楚如果收到一个字符串的话怎么处理的话就抛一个 ...



"让知道怎么处理这种情况的模块去处理"这就是exception的精髓了,推卸责任。

我都还没说这个模块是做什么的呢:)

假设这个模块是负责接收用户提交的表单,然后保存到数据库里面。如果这个模块都不知道怎么处理,还有哪个模块知道?

论坛徽章:
0
73 [报告]
发表于 2008-08-31 02:58 |只看该作者
原帖由 wwwsq 于 2008-8-31 02:46 发表



理论和实践是有距离的。

比如“Throw an exception to indicate failure in a constructor”,如果这个对象是个全局对象怎么办?
对于“Be sure that every resource acquired in a constructor is r ...

理0论和实践是有距离的。

说的很对

比如“Throw an exception to indicate failure in a constructor”,如果这个对象是个全局对象怎么办?

没办法。已经说的很清楚了:用局部的对象封装资源。
而且复杂的操作包括资源分配也不应该放在全局变量里。因为全局变量的构造、析构的时间是不确定的。

对于“Be sure that every resource acquired in a constructor is released when throwing an exception in that constructor”,在构造函数里面,压根就不应该出现exception什么的。否则你就要面对一系列诸如8,9,10,11,12,13这样的规则,而实际上没人能够切实做到这些规则

不明白为什么说不能出现execption

论坛徽章:
0
74 [报告]
发表于 2008-08-31 03:01 |只看该作者
我认为使用try/catch的难度在于上层函数捕捉到了异常也不知道该怎么办。比如下层函数抛出了一个NullReferenceException,上层函数能做什么?

使用try/catch的难度还在于,如何保证上层函数捕捉到了异常之后“会”进行处理。使用exception的软件里面,基本上都难以避免catch() thow;或者catch() {/*do nothing*/}这样的语句。

[ 本帖最后由 wwwsq 于 2008-8-31 03:02 编辑 ]

论坛徽章:
0
75 [报告]
发表于 2008-08-31 03:09 |只看该作者
原帖由 lgfang 于 2008-8-31 02:58 发表

说的很对

没办法。已经说的很清楚了:用局部的对象封装资源。
而且复杂的操作包括资源分配也不应该放在全局变量里。因为全局变量的构造、析构的时间是不确定的。

不明白为什么说不能出现execption



“用局部的对象封装资源”是没法保证的。因为当你定义一个class的时候,你无法保证它只在局部被构造。因为这个class的对象可能是另一个class的成员,层层嵌套之后,最终成为某个全局变量的成员。
除非这个class被明显的标明只能在局部使用,比如这个class是在cpp里面声明,而不放在头文件里面声明。

之所以“构造函数里面不能出现exception”,是因为为了允许“构造函数里面出现exception”,你需要严格的符合很多其他规则,否则这个class就会出问题。

为了一个坏的规则,你需要另外十个坏的规则来配合它。这是坏规则的典型特征。

如果允许在构造函数里面会抛出exception,那么A* p = new A();也会抛出异常,A a;也会抛出异常。这会让人发疯。

[ 本帖最后由 wwwsq 于 2008-8-31 03:13 编辑 ]

论坛徽章:
0
76 [报告]
发表于 2008-08-31 03:23 |只看该作者
我有时也会用class来保证资源释放。比如:
class mem_free
{
public:
  mem_free(data_unit* pUnit)
  {
    p = pUnit;
  }

  ~mem_free()
  {
    if(p) delete p;
  };

private:
  data_unit* p;
}

这种class只能放在cpp里面局部使用的,因为你明确知道自己在做什么。写成一个template class的话,反而可能因为滥用而带来其他问题。

[ 本帖最后由 wwwsq 于 2008-8-31 03:26 编辑 ]

论坛徽章:
0
77 [报告]
发表于 2008-08-31 03:24 |只看该作者
原帖由 wwwsq 于 2008-8-31 03:09 发表



“用局部的对象封装资源”是没法保证的。因为当你定义一个class的时候,你无法保证它只在局部被构造。因为这个class的对象可能是另一个class的成员,层层嵌套之后,最终成为某个全局变量的成员。
除非这 ...

我目前能想到的基本都可以封装到局部变量,例如:

  1. // theObj is the global variable you really want which will throw
  2. // exception in ctor, wrap it.
  3. class Wrapper {
  4. public:
  5.     ObjType getTheObj() {
  6.         if (!inited) {
  7.             theObj = new ObjType();
  8.         }
  9.         return theObj;
  10.     }

  11.     void tearDown() {
  12.         if (inited) {
  13.             delete theObj;
  14.         }
  15.     }

  16.     private:
  17.     bool inited;
  18.     ObjType* theObj;
  19. }

  20. Wrapper w; // only need to setup/teardown code at the very
  21.            // begining/end of main.
  22. int main() {
  23.     try {
  24.         w.getTheObj();
  25.     } catch (ExFromObj& obj) {
  26.         // error and quit
  27.     }

  28.     // other code

  29.     w.tearDown();
  30.     return 0;
  31. }
复制代码

论坛徽章:
0
78 [报告]
发表于 2008-08-31 03:30 |只看该作者
原帖由 wwwsq 于 2008-8-31 03:01 发表
我认为使用try/catch的难度在于上层函数捕捉到了异常也不知道该怎么办。比如下层函数抛出了一个NullReferenceException,上层函数能做什么?

使用try/catch的难度还在于,如何保证上层函数捕捉到了异常之后“ ...

》》我认为使用try/catch的难度在于上层函数捕捉到了异常也不知道该怎么办。比如下层函数抛出了一个NullReferenceException,上层函数能做什么?
上层不知道,就不捕捉,继续上传。总有知道的。如果都不知道,那么程序崩溃也没什么可说的。

》》使用try/catch的难度还在于,如何保证上层函数捕捉到了异常之后“会”进行处理。使用exception的软件里面,基本上都难以避免catch() thow;或者catch() {/*do nothing*/}这样的语句。
每个模块只负责管好自己。比方说你提供一个API负责转换字符串到整数,你的API不可能去管负责接收输入的模块怎么工作。如果你接收到错误输入抛出后,上层没处理,那是它不好。不能因为它不处理这种错误你的API就不抛异常(你根本不知道怎么办的情况下,不抛异常你又能做什么呢?)

[ 本帖最后由 lgfang 于 2008-8-31 11:42 编辑 ]

论坛徽章:
0
79 [报告]
发表于 2008-08-31 03:30 |只看该作者
原帖由 lgfang 于 2008-8-31 03:24 发表

我目前能想到的基本都可以封装到局部变量,例如:

// theObj is the global variable you really want which will throw
// exception in ctor, wrap it.
class Wrapper {
public:
    ObjType getThe ...




如果有个ObjType2需要有个ObjType成员怎么办?

class ObjType2
{
private:
  ObjType obj;
}

ObjType2 xxx;

int main()
{
  if (xxx.do_something())
  {
     //
  }
  return 0;
}

论坛徽章:
0
80 [报告]
发表于 2008-08-31 03:32 |只看该作者

回复 #74 wwwsq 的帖子

"让知道怎么处理这种情况的模块去处理"这就是exception的精髓了,推卸责任。

我都还没说这个模块是做什么的呢:)

假设这个模块是负责接收用户提交的表单,然后保存到数据库里面。如果这个模块都不知道怎么处理,还有哪个模块知道?


请不要断章取义:
当前context知道如何如何处理就处理了,不清楚的话才抛出异常让知道怎么处理这种情况的模块去处理。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP